From b55955f27360defb675870768bfbe688cd0e7adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 3 Sep 2018 15:52:59 +0200 Subject: [PATCH 01/48] Add basic concept for scm protocol --- .../scm/repository/api/RepositoryService.java | 13 ++++ .../sonia/scm/repository/api/ScmProtocol.java | 19 ++++++ .../scm/repository/spi/HttpScmProtocol.java | 15 +++++ .../spi/RepositoryServiceProvider.java | 8 ++- .../repository/api/RepositoryServiceTest.java | 65 +++++++++++++++++++ .../spi/GitRepositoryServiceProvider.java | 14 ++-- .../spi/HgRepositoryServiceProvider.java | 14 ++-- .../spi/SvnRepositoryServiceProvider.java | 14 ++-- 8 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java create mode 100644 scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java index 27eed6becd..926caad530 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java @@ -42,6 +42,7 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import java.io.Closeable; import java.io.IOException; +import java.util.Set; /** * From the {@link RepositoryService} it is possible to access all commands for @@ -358,4 +359,16 @@ public final class RepositoryService implements Closeable { } + public Set getSupportedProtocols() { + return provider.getSupportedProtocols(); + } + + public T getProtocol(Class clazz) { + for (ScmProtocol scmProtocol : getSupportedProtocols()) { + if (clazz.isAssignableFrom(scmProtocol.getClass())) { + return (T) scmProtocol; + } + } + throw new IllegalArgumentException("no implementation for " + clazz.getName() + " and repository type " + getRepository().getType()); + } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java new file mode 100644 index 0000000000..c987510491 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -0,0 +1,19 @@ +package sonia.scm.repository.api; + +/** + * An ScmProtocol represents a concrete protocol provided by the SCM-Manager instance + * to interact with a repository depending on its type. There may be multiple protocols + * available for a repository type (eg. http and ssh). + */ +public interface ScmProtocol { + + /** + * The type of the concrete protocol, eg. "http" or "ssh". + */ + String getType(); + + /** + * The URL to access the repository providing this protocol. + */ + String getUrl(); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java new file mode 100644 index 0000000000..76241808fb --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -0,0 +1,15 @@ +package sonia.scm.repository.spi; + +import sonia.scm.repository.api.ScmProtocol; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public interface HttpScmProtocol extends ScmProtocol { + @Override + default String getType() { + return "http"; + } + + void serve(HttpServletRequest request, HttpServletResponse response); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java index 976f38fffb..d44db74f7c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java @@ -38,15 +38,15 @@ package sonia.scm.repository.spi; import sonia.scm.repository.Feature; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.CommandNotSupportedException; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.ScmProtocol; import java.io.Closeable; import java.io.IOException; - import java.util.Collections; import java.util.Set; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -244,4 +244,6 @@ public abstract class RepositoryServiceProvider implements Closeable { throw new CommandNotSupportedException(Command.UNBUNDLE); } + + public abstract Set getSupportedProtocols(); } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java new file mode 100644 index 0000000000..f70e5a66a4 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -0,0 +1,65 @@ +package sonia.scm.repository.api; + +import org.junit.Test; +import sonia.scm.repository.Repository; +import sonia.scm.repository.spi.HttpScmProtocol; +import sonia.scm.repository.spi.RepositoryServiceProvider; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Collections; +import java.util.Set; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.util.IterableUtil.sizeOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class RepositoryServiceTest { + + private final RepositoryServiceProvider provider = mock(RepositoryServiceProvider.class); + private final Repository repository = mock(Repository.class); + + @Test + public void shouldReturnProtocolsFromProvider() { + when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol())); + + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); + Set supportedProtocols = repositoryService.getSupportedProtocols(); + + assertThat(sizeOf(supportedProtocols)).isEqualTo(1); + } + + @Test + public void shouldFindProtocolFromProvider() { + when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol())); + + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); + HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); + + assertThat(protocol.getUrl()).isEqualTo("dummy"); + } + + @Test + public void shouldFailForUnknownProtocol() { + when(provider.getSupportedProtocols()).thenReturn(Collections.emptySet()); + + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); + + assertThrows(IllegalArgumentException.class, () -> { + repositoryService.getProtocol(HttpScmProtocol.class); + }); + } + + private static class DummyHttpProtocol implements HttpScmProtocol { + @Override + public String getUrl() { + return "dummy"; + } + + @Override + public void serve(HttpServletRequest request, HttpServletResponse response) { + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 7ea26de83f..2fbbf3b029 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -36,17 +36,17 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.collect.ImmutableSet; - import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.ScmProtocol; import java.io.IOException; - +import java.util.Collections; import java.util.Set; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -248,6 +248,12 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider return new GitTagsCommand(context, repository); } + @Override + public Set getSupportedProtocols() { + // TODO #9246 + return Collections.emptySet(); + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 4295bf45e4..11697ecea6 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -36,21 +36,21 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.io.Closeables; - import sonia.scm.repository.Feature; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.ScmProtocol; import java.io.File; import java.io.IOException; - +import java.util.Collections; import java.util.EnumSet; import java.util.Set; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -273,6 +273,12 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider return new HgTagsCommand(context, repository); } + @Override + public Set getSupportedProtocols() { + // TODO #9248 + return Collections.emptySet(); + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java index 24180bfe9e..3b246cff2e 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java @@ -37,17 +37,17 @@ package sonia.scm.repository.spi; import com.google.common.collect.ImmutableSet; import com.google.common.io.Closeables; - import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.api.Command; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.ScmProtocol; import java.io.IOException; - +import java.util.Collections; import java.util.Set; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -191,6 +191,12 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider return new SvnUnbundleCommand(context, repository); } + @Override + public Set getSupportedProtocols() { + // TODO #9247 + return Collections.emptySet(); + } + //~--- fields --------------------------------------------------------------- /** Field description */ From 3f772b3688e789a5c96a0f04889f85fcc5be0468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 4 Sep 2018 12:40:41 +0200 Subject: [PATCH 02/48] Use links from protocols instead of resource links Add links only for requests with according permissions --- .../scm/repository/api/RepositoryService.java | 4 +- .../sonia/scm/repository/api/ScmProtocol.java | 4 +- .../repository/api/RepositoryServiceTest.java | 9 +-- .../RepositoryToRepositoryDtoMapper.java | 21 ++++++- .../scm/api/v2/resources/ResourceLinks.java | 5 -- .../scm/api/v2/resources/MockScmProtocol.java | 25 ++++++++ .../resources/RepositoryRootResourceTest.java | 24 +++++++- .../RepositoryToRepositoryDtoMapperTest.java | 58 +++++++++++++++++-- .../resources/sonia/scm/repository/shiro.ini | 2 + 9 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 scm-webapp/src/test/java/sonia/scm/api/v2/resources/MockScmProtocol.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java index 926caad530..61c3ce5d87 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java @@ -42,7 +42,7 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import java.io.Closeable; import java.io.IOException; -import java.util.Set; +import java.util.Collection; /** * From the {@link RepositoryService} it is possible to access all commands for @@ -359,7 +359,7 @@ public final class RepositoryService implements Closeable { } - public Set getSupportedProtocols() { + public Collection getSupportedProtocols() { return provider.getSupportedProtocols(); } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java index c987510491..0bd1ed77ef 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -1,5 +1,7 @@ package sonia.scm.repository.api; +import javax.ws.rs.core.UriInfo; + /** * An ScmProtocol represents a concrete protocol provided by the SCM-Manager instance * to interact with a repository depending on its type. There may be multiple protocols @@ -15,5 +17,5 @@ public interface ScmProtocol { /** * The URL to access the repository providing this protocol. */ - String getUrl(); + String getUrl(UriInfo uriInfo); } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index f70e5a66a4..c5e38908ec 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -7,8 +7,9 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; +import java.util.Collection; import java.util.Collections; -import java.util.Set; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.util.IterableUtil.sizeOf; @@ -26,7 +27,7 @@ public class RepositoryServiceTest { when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol())); RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); - Set supportedProtocols = repositoryService.getSupportedProtocols(); + Collection supportedProtocols = repositoryService.getSupportedProtocols(); assertThat(sizeOf(supportedProtocols)).isEqualTo(1); } @@ -38,7 +39,7 @@ public class RepositoryServiceTest { RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); - assertThat(protocol.getUrl()).isEqualTo("dummy"); + assertThat(protocol.getUrl(null)).isEqualTo("dummy"); } @Test @@ -54,7 +55,7 @@ public class RepositoryServiceTest { private static class DummyHttpProtocol implements HttpScmProtocol { @Override - public String getUrl() { + public String getUrl(UriInfo uriInfo) { return "dummy"; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index f76669fbb9..0bc9b7af48 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -1,6 +1,7 @@ package sonia.scm.api.v2.resources; import com.google.inject.Inject; +import de.otto.edison.hal.Link; import de.otto.edison.hal.Links; import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; @@ -11,9 +12,14 @@ import sonia.scm.repository.RepositoryPermissions; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.repository.api.ScmProtocol; + +import java.util.Collection; +import java.util.List; import static de.otto.edison.hal.Link.link; import static de.otto.edison.hal.Links.linkingTo; +import static java.util.stream.Collectors.toList; // Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection. @SuppressWarnings("squid:S3306") @@ -24,13 +30,14 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper supportedProtocols = repositoryService.getSupportedProtocols(); + List protocolLinks = supportedProtocols + .stream() + .map(this::createProtocolLink) + .collect(toList()); + linksBuilder.array(protocolLinks); + } if (repositoryService.isSupported(Command.TAGS)) { linksBuilder.single(link("tags", resourceLinks.tag().all(target.getNamespace(), target.getName()))); } @@ -50,4 +65,8 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper createSingletonPageResult(Repository repository) { return new PageResult<>(singletonList(repository), 0); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java index 0c77d40023..9fe2700e4a 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java @@ -7,7 +7,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.mockito.Answers; import org.mockito.InjectMocks; import org.mockito.Mock; import sonia.scm.repository.HealthCheckFailure; @@ -15,13 +14,18 @@ import sonia.scm.repository.Permission; import sonia.scm.repository.PermissionType; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; +import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.repository.api.ScmProtocol; import java.net.URI; +import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -39,8 +43,12 @@ public class RepositoryToRepositoryDtoMapperTest { private final URI baseUri = URI.create("http://example.com/base/"); @SuppressWarnings("unused") // Is injected private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); - @Mock(answer = Answers.RETURNS_DEEP_STUBS) + @Mock//(answer = Answers.RETURNS_DEEP_STUBS) private RepositoryServiceFactory serviceFactory; + @Mock + private RepositoryService repositoryService; + @Mock + private UriInfoStore uriInfoStore; @InjectMocks private RepositoryToRepositoryDtoMapperImpl mapper; @@ -48,7 +56,9 @@ public class RepositoryToRepositoryDtoMapperTest { @Before public void init() { initMocks(this); - when(serviceFactory.create(any(Repository.class)).isSupported(any(Command.class))).thenReturn(true); + when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); + when(repositoryService.isSupported(any(Command.class))).thenReturn(true); + when(repositoryService.getSupportedProtocols()).thenReturn(emptySet()); } @After @@ -129,14 +139,14 @@ public class RepositoryToRepositoryDtoMapperTest { @Test public void shouldNotCreateTagsLink_ifNotSupported() { - when(serviceFactory.create(any(Repository.class)).isSupported(Command.TAGS)).thenReturn(false); + when(repositoryService.isSupported(Command.TAGS)).thenReturn(false); RepositoryDto dto = mapper.map(createTestRepository()); assertFalse(dto.getLinks().getLinkBy("tags").isPresent()); } @Test public void shouldNotCreateBranchesLink_ifNotSupported() { - when(serviceFactory.create(any(Repository.class)).isSupported(Command.BRANCHES)).thenReturn(false); + when(repositoryService.isSupported(Command.BRANCHES)).thenReturn(false); RepositoryDto dto = mapper.map(createTestRepository()); assertFalse(dto.getLinks().getLinkBy("branches").isPresent()); } @@ -165,6 +175,43 @@ public class RepositoryToRepositoryDtoMapperTest { dto.getLinks().getLinkBy("permissions").get().getHref()); } + @Test + public void shouldCreateCorrectProtocolLinks() { + when(repositoryService.getSupportedProtocols()).thenReturn( + asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + ); + + RepositoryDto dto = mapper.map(createTestRepository()); + assertTrue("should contain http link", dto.getLinks().stream().anyMatch(l -> l.getName().equals("http") && l.getHref().equals("http://scm"))); + assertTrue("should contain other link", dto.getLinks().stream().anyMatch(l -> l.getName().equals("other") && l.getHref().equals("some://protocol"))); + } + + @Test + @SubjectAware(username = "community") + public void shouldCreateProtocolLinksForPullPermission() { + when(repositoryService.getSupportedProtocols()).thenReturn( + asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + ); + + RepositoryDto dto = mapper.map(createTestRepository()); + assertEquals(2, dto.getLinks().getLinksBy("protocol").size()); + } + + @Test + @SubjectAware(username = "unpriv") + public void shouldNotCreateProtocolLinksWithoutPullPermission() { + when(repositoryService.getSupportedProtocols()).thenReturn( + asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + ); + + RepositoryDto dto = mapper.map(createTestRepository()); + assertTrue(dto.getLinks().getLinksBy("protocol").isEmpty()); + } + + private ScmProtocol mockProtocol(String type, String protocol) { + return new MockScmProtocol(type, protocol); + } + private Repository createTestRepository() { Repository repository = new Repository(); repository.setNamespace("testspace"); @@ -179,4 +226,5 @@ public class RepositoryToRepositoryDtoMapperTest { return repository; } + } diff --git a/scm-webapp/src/test/resources/sonia/scm/repository/shiro.ini b/scm-webapp/src/test/resources/sonia/scm/repository/shiro.ini index 5073bf398d..9a39a2d46c 100644 --- a/scm-webapp/src/test/resources/sonia/scm/repository/shiro.ini +++ b/scm-webapp/src/test/resources/sonia/scm/repository/shiro.ini @@ -3,9 +3,11 @@ trillian = secret, admin dent = secret, creator, heartOfGold, puzzle42 unpriv = secret crato = secret, creator +community = secret, oss [roles] admin = * creator = repository:create heartOfGold = "repository:read,modify,delete:hof" puzzle42 = "repository:read,write:p42" +oss = "repository:pull" From c4b34752b495078225e83ccd013504b808b1a5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 4 Sep 2018 20:29:17 +0200 Subject: [PATCH 03/48] Fix integration tests by delegating to existing servlets --- .../java/sonia/scm/repository/Repository.java | 12 ---- .../sonia/scm/repository/api/ScmProtocol.java | 4 +- .../spi/DefaultHttpScmProtocol.java | 20 +++++++ .../scm/repository/spi/HttpScmProtocol.java | 4 +- .../sonia/scm/repository/RepositoryTest.java | 60 ------------------- .../repository/api/RepositoryServiceTest.java | 4 +- .../java/sonia/scm/it/RepositoryUtil.java | 2 +- .../spi/GitRepositoryServiceProvider.java | 4 +- .../java/sonia/scm/web/ScmGitServlet.java | 16 ++++- .../spi/HgRepositoryServiceProvider.java | 4 +- .../main/java/sonia/scm/web/HgCGIServlet.java | 15 ++++- .../spi/SvnRepositoryServiceProvider.java | 4 +- .../java/sonia/scm/web/SvnDAVServlet.java | 15 ++++- .../resources/RepositoryRootResource.java | 31 +++------- .../RepositoryToRepositoryDtoMapper.java | 6 +- .../scm/api/v2/resources/MockScmProtocol.java | 3 +- 16 files changed, 90 insertions(+), 114 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java delete mode 100644 scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index 0d8c6a6af8..cad36f2d88 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -40,7 +40,6 @@ import com.google.common.base.Objects; import com.google.common.collect.Lists; import sonia.scm.BasicPropertiesAware; import sonia.scm.ModelObject; -import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; import sonia.scm.util.ValidationUtil; @@ -349,17 +348,6 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per // do not copy health check results } - /** - * Creates the url of the repository. - * - * @param baseUrl base url of the server including the context path - * @return url of the repository - * @since 1.17 - */ - public String createUrl(String baseUrl) { - return HttpUtil.concatenate(baseUrl, type, namespace, name); - } - /** * Returns true if the {@link Repository} is the same as the obj argument. * diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java index 0bd1ed77ef..8d44ec19ad 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -1,5 +1,7 @@ package sonia.scm.repository.api; +import sonia.scm.repository.Repository; + import javax.ws.rs.core.UriInfo; /** @@ -17,5 +19,5 @@ public interface ScmProtocol { /** * The URL to access the repository providing this protocol. */ - String getUrl(UriInfo uriInfo); + String getUrl(Repository repository, UriInfo uriInfo); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java new file mode 100644 index 0000000000..223be7aca8 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java @@ -0,0 +1,20 @@ +package sonia.scm.repository.spi; + +import sonia.scm.repository.Repository; + +import javax.ws.rs.core.UriInfo; +import java.net.URI; + +public abstract class DefaultHttpScmProtocol implements HttpScmProtocol { + + private final Repository repository; + + protected DefaultHttpScmProtocol(Repository repository) { + this.repository = repository; + } + + @Override + public String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../" + this.repository.getType() + "/" + this.repository.getNamespace() + "/" + this.repository.getName())).toASCIIString(); + } +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index 76241808fb..2bf46c384d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -2,8 +2,10 @@ package sonia.scm.repository.spi; import sonia.scm.repository.api.ScmProtocol; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; public interface HttpScmProtocol extends ScmProtocol { @Override @@ -11,5 +13,5 @@ public interface HttpScmProtocol extends ScmProtocol { return "http"; } - void serve(HttpServletRequest request, HttpServletResponse response); + void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; } diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java deleted file mode 100644 index f13f4cbc67..0000000000 --- a/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - -package sonia.scm.repository; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * - * @author Sebastian Sdorra - */ -public class RepositoryTest -{ - - /** - * Method description - * - */ - @Test - public void testCreateUrl() - { - Repository repository = new Repository("123", "hg", "test", "repo"); - - assertEquals("http://localhost:8080/scm/hg/test/repo", - repository.createUrl("http://localhost:8080/scm")); - assertEquals("http://localhost:8080/scm/hg/test/repo", - repository.createUrl("http://localhost:8080/scm/")); - } -} diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index c5e38908ec..7addb448f6 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -39,7 +39,7 @@ public class RepositoryServiceTest { RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); - assertThat(protocol.getUrl(null)).isEqualTo("dummy"); + assertThat(protocol.getUrl(repository, null)).isEqualTo("dummy"); } @Test @@ -55,7 +55,7 @@ public class RepositoryServiceTest { private static class DummyHttpProtocol implements HttpScmProtocol { @Override - public String getUrl(UriInfo uriInfo) { + public String getUrl(Repository repository, UriInfo uriInfo) { return "dummy"; } diff --git a/scm-it/src/test/java/sonia/scm/it/RepositoryUtil.java b/scm-it/src/test/java/sonia/scm/it/RepositoryUtil.java index ef2332074b..b4690768fc 100644 --- a/scm-it/src/test/java/sonia/scm/it/RepositoryUtil.java +++ b/scm-it/src/test/java/sonia/scm/it/RepositoryUtil.java @@ -24,7 +24,7 @@ public class RepositoryUtil { static RepositoryClient createRepositoryClient(String repositoryType, File folder, String username, String password) throws IOException { String httpProtocolUrl = TestData.callRepository(username, password, repositoryType, HttpStatus.SC_OK) .extract() - .path("_links.httpProtocol.href"); + .path("_links.protocol.find{it.name=='http'}.href"); return REPOSITORY_CLIENT_FACTORY.create(repositoryType, httpProtocolUrl, username, password, folder); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 2fbbf3b029..56ceb59de0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -40,6 +40,7 @@ import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; +import sonia.scm.web.ScmGitServlet; import java.io.IOException; import java.util.Collections; @@ -250,8 +251,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - // TODO #9246 - return Collections.emptySet(); + return Collections.singleton(new ScmGitServlet(null, null, null, null, null, null)); } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java index 5612a64652..5efffec523 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java @@ -44,6 +44,7 @@ import org.slf4j.Logger; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; +import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.util.HttpUtil; import sonia.scm.web.lfs.servlet.LfsServletFactory; @@ -51,7 +52,9 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; import java.io.IOException; +import java.net.URI; import java.util.regex.Pattern; import static org.eclipse.jgit.lfs.lib.Constants.CONTENT_TYPE_GIT_LFS_JSON; @@ -64,7 +67,7 @@ import static org.slf4j.LoggerFactory.getLogger; * @author Sebastian Sdorra */ @Singleton -public class ScmGitServlet extends GitServlet +public class ScmGitServlet extends GitServlet implements HttpScmProtocol { /** Field description */ @@ -284,6 +287,16 @@ public class ScmGitServlet extends GitServlet return false; } + @Override + public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + service(request, response); + } + + @Override + public String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../git/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + } + //~--- fields --------------------------------------------------------------- @@ -299,5 +312,4 @@ public class ScmGitServlet extends GitServlet private final GitRepositoryViewer repositoryViewer; private final LfsServletFactory lfsServletFactory; - } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 11697ecea6..882c5a1c6b 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -42,6 +42,7 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; +import sonia.scm.web.HgCGIServlet; import java.io.File; import java.io.IOException; @@ -275,8 +276,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - // TODO #9248 - return Collections.emptySet(); + return Collections.singleton(new HgCGIServlet(null, null, null, null, null, null)); } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index 6cb4d523f0..a8fbf0431e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -51,6 +51,7 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; +import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.security.CipherUtil; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; @@ -63,8 +64,10 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.ws.rs.core.UriInfo; import java.io.File; import java.io.IOException; +import java.net.URI; import java.util.Base64; import java.util.Enumeration; @@ -75,7 +78,7 @@ import java.util.Enumeration; * @author Sebastian Sdorra */ @Singleton -public class HgCGIServlet extends HttpServlet +public class HgCGIServlet extends HttpServlet implements HttpScmProtocol { /** Field description */ @@ -359,6 +362,16 @@ public class HgCGIServlet extends HttpServlet return python; } + @Override + public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + service(request, response); + } + + @Override + public String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../hg/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java index 3b246cff2e..cbd303a9c6 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java @@ -41,6 +41,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; +import sonia.scm.web.SvnDAVServlet; import java.io.IOException; import java.util.Collections; @@ -193,8 +194,7 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - // TODO #9247 - return Collections.emptySet(); + return Collections.singleton(new SvnDAVServlet(null, null, null, null)); } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index c811179255..c968763955 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -45,6 +45,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; @@ -52,7 +53,9 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; import java.io.IOException; +import java.net.URI; //~--- JDK imports ------------------------------------------------------------ @@ -61,7 +64,7 @@ import java.io.IOException; * @author Sebastian Sdorra */ @Singleton -public class SvnDAVServlet extends DAVServlet +public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol { /** Field description */ @@ -283,6 +286,16 @@ public class SvnDAVServlet extends DAVServlet private final RepositoryProvider repositoryProvider; } + @Override + public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + service(request, response); + } + + @Override + public String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../svn/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + } + //~--- fields --------------------------------------------------------------- diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java index cec1894764..59ffbe560b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java @@ -40,30 +40,26 @@ import com.google.common.collect.Collections2; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.inject.Inject; - import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryTypePredicate; +import sonia.scm.template.Viewable; import sonia.scm.util.HttpUtil; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - import javax.servlet.http.HttpServletRequest; - import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import sonia.scm.template.Viewable; +import java.io.IOException; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +//~--- JDK imports ------------------------------------------------------------ /** * @@ -175,17 +171,6 @@ public class RepositoryRootResource return repository; } - /** - * Method description - * - * - * @return - */ - public String getUrl() - { - return repository.createUrl(baseUrl); - } - //~--- fields ------------------------------------------------------------- /** Field description */ diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index 0bc9b7af48..bc0073506e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -50,7 +50,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper supportedProtocols = repositoryService.getSupportedProtocols(); List protocolLinks = supportedProtocols .stream() - .map(this::createProtocolLink) + .map(protocol -> createProtocolLink(protocol, repository)) .collect(toList()); linksBuilder.array(protocolLinks); } @@ -66,7 +66,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Thu, 6 Sep 2018 10:58:09 +0200 Subject: [PATCH 04/48] Add POC protocol servlet with delegate to git --- .../scm/repository/RepositoryProvider.java | 28 ++---- .../spi/GitRepositoryServiceProvider.java | 17 ++-- .../spi/GitRepositoryServiceResolver.java | 18 ++-- .../java/sonia/scm/web/GitServletModule.java | 3 - .../java/sonia/scm/ScmContextListener.java | 2 +- .../main/java/sonia/scm/ScmServletModule.java | 56 ++++++++---- .../java/sonia/scm/WebResourceServlet.java | 2 +- .../repository/DefaultRepositoryManager.java | 48 +---------- .../repository/DefaultRepositoryProvider.java | 70 +++------------ .../scm/web/protocol/HttpProtocolServlet.java | 86 +++++++++++++++++++ 10 files changed, 163 insertions(+), 167 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryProvider.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryProvider.java index 1a5300ad21..cea8574d14 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryProvider.java @@ -6,13 +6,13 @@ * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,35 +26,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.throwingproviders.CheckedProvider; -import sonia.scm.security.ScmSecurityException; - /** * * @author Sebastian Sdorra * @since 1.10 */ -public interface RepositoryProvider extends CheckedProvider -{ - - /** - * Method description - * - * - * @return - * - * @throws ScmSecurityException - */ +public interface RepositoryProvider extends CheckedProvider { @Override - public Repository get() throws ScmSecurityException; + Repository get(); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 56ceb59de0..45a0ad5347 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -42,6 +42,7 @@ import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; import sonia.scm.web.ScmGitServlet; +import javax.inject.Provider; import java.io.IOException; import java.util.Collections; import java.util.Set; @@ -74,19 +75,13 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * - * @param handler - * @param repository - */ public GitRepositoryServiceProvider(GitRepositoryHandler handler, - Repository repository) + Repository repository, Provider servletProvider) { this.handler = handler; this.repository = repository; - context = new GitContext(handler.getDirectory(repository)); + this.servletProvider = servletProvider; + this.context = new GitContext(handler.getDirectory(repository)); } //~--- methods -------------------------------------------------------------- @@ -251,7 +246,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - return Collections.singleton(new ScmGitServlet(null, null, null, null, null, null)); + return Collections.singleton(servletProvider.get()); } //~--- fields --------------------------------------------------------------- @@ -264,4 +259,6 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private Repository repository; + + private final Provider servletProvider; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index 52c5171627..2cecb964fe 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -35,10 +35,12 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; - import sonia.scm.plugin.Extension; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; +import sonia.scm.web.ScmGitServlet; + +import javax.inject.Provider; /** * @@ -53,16 +55,11 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * - * @param handler - */ @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler) + public GitRepositoryServiceResolver(GitRepositoryHandler handler, Provider servletProvider) { this.handler = handler; + this.servletProvider = servletProvider; } //~--- methods -------------------------------------------------------------- @@ -82,7 +79,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new GitRepositoryServiceProvider(handler, repository); + provider = new GitRepositoryServiceProvider(handler, repository, servletProvider); } return provider; @@ -91,5 +88,6 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver //~--- fields --------------------------------------------------------------- /** Field description */ - private GitRepositoryHandler handler; + private final GitRepositoryHandler handler; + private final Provider servletProvider; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index bdad103c15..94e772123e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -75,8 +75,5 @@ public class GitServletModule extends ServletModule bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass()); bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass()); - - // serlvelts and filters - serve(PATTERN_GIT).with(ScmGitServlet.class); } } diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index 1eaef333a1..cb272de38f 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -135,7 +135,7 @@ public class ScmContextListener extends GuiceResteasyBootstrapServletContextList moduleList.add(new EagerSingletonModule()); moduleList.add(ShiroWebModule.guiceFilterModule()); moduleList.add(new WebElementModule(pluginLoader)); - moduleList.add(new ScmServletModule(context, pluginLoader, overrides, pluginLoader.getExtensionProcessor())); + moduleList.add(new ScmServletModule(context, pluginLoader, overrides)); moduleList.add( new ScmSecurityModule(context, pluginLoader.getExtensionProcessor()) ); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 1d627de8ed..2ea17e9da3 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -56,17 +56,48 @@ import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.io.DefaultFileSystem; import sonia.scm.io.FileSystem; import sonia.scm.net.SSLContextProvider; -import sonia.scm.net.ahc.*; -import sonia.scm.plugin.*; -import sonia.scm.repository.*; +import sonia.scm.net.ahc.AdvancedHttpClient; +import sonia.scm.net.ahc.ContentTransformer; +import sonia.scm.net.ahc.DefaultAdvancedHttpClient; +import sonia.scm.net.ahc.JsonContentTransformer; +import sonia.scm.net.ahc.XmlContentTransformer; +import sonia.scm.plugin.DefaultPluginLoader; +import sonia.scm.plugin.DefaultPluginManager; +import sonia.scm.plugin.PluginLoader; +import sonia.scm.plugin.PluginManager; +import sonia.scm.repository.DefaultRepositoryManager; +import sonia.scm.repository.DefaultRepositoryProvider; +import sonia.scm.repository.HealthCheckContextListener; +import sonia.scm.repository.NamespaceStrategy; +import sonia.scm.repository.NamespaceStrategyProvider; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryDAO; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.RepositoryManagerProvider; +import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.api.HookContextFactory; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.spi.HookEventFacade; import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.schedule.QuartzScheduler; import sonia.scm.schedule.Scheduler; -import sonia.scm.security.*; -import sonia.scm.store.*; +import sonia.scm.security.AuthorizationChangedEventProducer; +import sonia.scm.security.CipherHandler; +import sonia.scm.security.CipherUtil; +import sonia.scm.security.ConfigurableLoginAttemptHandler; +import sonia.scm.security.DefaultKeyGenerator; +import sonia.scm.security.DefaultSecuritySystem; +import sonia.scm.security.KeyGenerator; +import sonia.scm.security.LoginAttemptHandler; +import sonia.scm.security.SecuritySystem; +import sonia.scm.store.BlobStoreFactory; +import sonia.scm.store.ConfigurationEntryStoreFactory; +import sonia.scm.store.ConfigurationStoreFactory; +import sonia.scm.store.DataStoreFactory; +import sonia.scm.store.FileBlobStoreFactory; +import sonia.scm.store.JAXBConfigurationEntryStoreFactory; +import sonia.scm.store.JAXBConfigurationStoreFactory; +import sonia.scm.store.JAXBDataStoreFactory; import sonia.scm.template.MustacheTemplateEngine; import sonia.scm.template.TemplateEngine; import sonia.scm.template.TemplateEngineFactory; @@ -81,6 +112,7 @@ import sonia.scm.util.ScmConfigurationUtil; import sonia.scm.web.UserAgentParser; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.DefaultCGIExecutorFactory; +import sonia.scm.web.filter.AuthenticationFilter; import sonia.scm.web.filter.LoggingFilter; import sonia.scm.web.security.AdministrationContext; import sonia.scm.web.security.DefaultAdministrationContext; @@ -162,15 +194,12 @@ public class ScmServletModule extends ServletModule * @param servletContext * @param pluginLoader * @param overrides - * @param extensionProcessor */ - ScmServletModule(ServletContext servletContext, - DefaultPluginLoader pluginLoader, ClassOverrides overrides, ExtensionProcessor extensionProcessor) + ScmServletModule(ServletContext servletContext, DefaultPluginLoader pluginLoader, ClassOverrides overrides) { this.servletContext = servletContext; this.pluginLoader = pluginLoader; this.overrides = overrides; - this.extensionProcessor = extensionProcessor; } //~--- methods -------------------------------------------------------------- @@ -293,6 +322,8 @@ public class ScmServletModule extends ServletModule bind(TemplateEngineFactory.class); bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class); + filter("/repo/*").through(AuthenticationFilter.class); + // bind events // bind(LastModifiedUpdateListener.class); @@ -389,11 +420,6 @@ public class ScmServletModule extends ServletModule /** * Load ScmConfiguration with JAXB - * - * - * @param context - * - * @return */ private ScmConfiguration getScmConfiguration() { @@ -414,6 +440,4 @@ public class ScmServletModule extends ServletModule /** Field description */ private final ServletContext servletContext; - - private final ExtensionProcessor extensionProcessor; } diff --git a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java index 764e4f18d2..ce3e3fa4e1 100644 --- a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java @@ -33,7 +33,7 @@ public class WebResourceServlet extends HttpServlet { * TODO remove old protocol servlets and hook. Move /hook/hg to api? */ @VisibleForTesting - static final String PATTERN = "/(?!api/|git/|hg/|svn/|hook/).*"; + static final String PATTERN = "/(?!api/|git/|hg/|svn/|hook/|repo/).*"; private static final Logger LOG = LoggerFactory.getLogger(WebResourceServlet.class); diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 02ae67719b..06f92f7bec 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -34,7 +34,6 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import com.github.sdorra.ssp.PermissionActionCheck; -import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.inject.Inject; @@ -43,7 +42,6 @@ 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; @@ -332,52 +330,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { uri = uri.substring(1); } - int typeSeparator = uri.indexOf(HttpUtil.SEPARATOR_PATH); Repository repository = null; - if (typeSeparator > 0) { - String type = uri.substring(0, typeSeparator); + String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH)); + String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1)); - uri = uri.substring(typeSeparator + 1); - repository = getFromTypeAndUri(type, uri); - } - - return repository; - } - - private Repository getFromTypeAndUri(String type, String uri) { - if (Strings.isNullOrEmpty(type)) { - throw new ArgumentIsInvalidException("argument type is required"); - } - - if (Strings.isNullOrEmpty(uri)) { - throw new ArgumentIsInvalidException("argument uri is required"); - } - - // remove ;jsessionid, jetty bug? - uri = HttpUtil.removeMatrixParameter(uri); - - Repository repository = null; - - if (handlerMap.containsKey(type)) { - Collection repositories = repositoryDAO.getAll(); - - PermissionActionCheck check = RepositoryPermissions.read(); - - for (Repository r : repositories) { - if (repositoryMatcher.matches(r, type, uri)) { - check.check(r); - repository = r.clone(); - - break; - } - } - } - - if ((repository == null) && logger.isDebugEnabled()) { - logger.debug("could not find repository with type {} and uri {}", type, - uri); - } + repository = get(new NamespaceAndName(namespace, name)); return repository; } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java index c3341bbd22..3f061ff46d 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java @@ -38,81 +38,31 @@ package sonia.scm.repository; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.servlet.RequestScoped; - import sonia.scm.security.ScmSecurityException; -//~--- JDK imports ------------------------------------------------------------ - import javax.servlet.http.HttpServletRequest; -/** - * - * @author Sebastian Sdorra - */ -@RequestScoped -public class DefaultRepositoryProvider implements RepositoryProvider -{ +//~--- JDK imports ------------------------------------------------------------ + +@RequestScoped +public class DefaultRepositoryProvider implements RepositoryProvider { - /** Field description */ public static final String ATTRIBUTE_NAME = "scm.request.repository"; - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - * - * @param requestProvider - * @param manager - */ + private final Provider requestProvider; @Inject - public DefaultRepositoryProvider( - Provider requestProvider, - RepositoryManager manager) - { + public DefaultRepositoryProvider(Provider requestProvider) { this.requestProvider = requestProvider; - this.manager = manager; } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - * - * @throws ScmSecurityException - */ @Override - public Repository get() throws ScmSecurityException - { - Repository repository = null; + public Repository get() throws ScmSecurityException { HttpServletRequest request = requestProvider.get(); - if (request != null) - { - repository = (Repository) request.getAttribute(ATTRIBUTE_NAME); - - if (repository == null) - { - repository = manager.getFromRequest(request); - - if (repository != null) - { - request.setAttribute(ATTRIBUTE_NAME, repository); - } - } + if (request != null) { + return (Repository) request.getAttribute(ATTRIBUTE_NAME); } - return repository; + throw new IllegalStateException("request not found"); } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private final RepositoryManager manager; - - /** Field description */ - private final Provider requestProvider; } diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java new file mode 100644 index 0000000000..7991cbb596 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java @@ -0,0 +1,86 @@ +package sonia.scm.web.protocol; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import sonia.scm.PushStateDispatcher; +import sonia.scm.filter.WebElement; +import sonia.scm.repository.DefaultRepositoryProvider; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.RepositoryNotFoundException; +import sonia.scm.repository.RepositoryProvider; +import sonia.scm.repository.api.RepositoryService; +import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.repository.spi.HttpScmProtocol; +import sonia.scm.util.HttpUtil; +import sonia.scm.web.UserAgent; +import sonia.scm.web.UserAgentParser; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Singleton +@WebElement(value = HttpProtocolServlet.PATTERN) +@Slf4j +public class HttpProtocolServlet extends HttpServlet { + + public static final String PATTERN = "/repo/*"; + + private final RepositoryProvider repositoryProvider; + private final RepositoryServiceFactory serviceFactory; + + private final Provider requestProvider; + + private final PushStateDispatcher dispatcher; + private final UserAgentParser userAgentParser; + + @Inject + public HttpProtocolServlet(RepositoryProvider repositoryProvider, RepositoryServiceFactory serviceFactory, Provider requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser) { + this.repositoryProvider = repositoryProvider; + this.serviceFactory = serviceFactory; + this.requestProvider = requestProvider; + this.dispatcher = dispatcher; + this.userAgentParser = userAgentParser; + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Subject subject = SecurityUtils.getSubject(); + + + UserAgent userAgent = userAgentParser.parse(req); + if (userAgent.isBrowser()) { + log.trace("dispatch browser request for user agent {}", userAgent); + dispatcher.dispatch(req, resp, req.getRequestURI()); + } else { + + + String pathInfo = req.getPathInfo(); + NamespaceAndName namespaceAndName = fromUri(pathInfo); + try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) { + requestProvider.get().setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repositoryService.getRepository()); + HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); + protocol.serve(req, resp); + } catch (RepositoryNotFoundException e) { + resp.setStatus(404); + } + } + } + + private NamespaceAndName fromUri(String uri) { + if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) { + uri = uri.substring(1); + } + + String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH)); + String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1)); + + return new NamespaceAndName(namespace, name); + } +} From 4eb75bc621bf0769236256b1727ae6d5f85e19ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 6 Sep 2018 15:33:24 +0200 Subject: [PATCH 05/48] Initialize servlet and fix paths --- .../scm/repository/spi/HttpScmProtocol.java | 3 +- .../InitializingHttpScmProtocolWrapper.java | 44 ++++++++++++ .../repository/api/RepositoryServiceTest.java | 3 +- .../spi/GitRepositoryServiceProvider.java | 10 ++- .../spi/GitRepositoryServiceResolver.java | 8 +-- .../scm/web/GitBasicAuthenticationFilter.java | 69 ------------------- .../sonia/scm/web/GitPermissionFilter.java | 17 ++--- .../sonia/scm/web/GitRepositoryResolver.java | 3 +- .../web/GitScmProtocolProviderWrapper.java | 15 ++++ .../java/sonia/scm/web/GitServletModule.java | 2 +- .../java/sonia/scm/web/ScmGitServlet.java | 18 +---- .../web/lfs/servlet/LfsServletFactory.java | 2 +- .../main/java/sonia/scm/web/HgCGIServlet.java | 3 +- .../java/sonia/scm/web/SvnDAVServlet.java | 3 +- .../scm/web/protocol/HttpProtocolServlet.java | 2 +- 15 files changed, 87 insertions(+), 115 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java delete mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index 2bf46c384d..c19205c1e7 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -2,6 +2,7 @@ package sonia.scm.repository.spi; import sonia.scm.repository.api.ScmProtocol; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -13,5 +14,5 @@ public interface HttpScmProtocol extends ScmProtocol { return "http"; } - void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; + void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java new file mode 100644 index 0000000000..ad0e7cb513 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -0,0 +1,44 @@ +package sonia.scm.repository.spi; + +import sonia.scm.repository.Repository; + +import javax.inject.Provider; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; + +public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProtocol { + + private final Provider delegateProvider; + + private volatile boolean isInitialized = false; + + + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider) { + this.delegateProvider = delegateProvider; + } + + @Override + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { + if (!isInitialized) { + synchronized (this) { + if (!isInitialized) { + delegateProvider.get().init(config); + isInitialized = true; + } + } + } + delegateProvider.get().service(request, response); + } + + + @Override + public String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + } +} diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index 7addb448f6..8d37c0e187 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -5,6 +5,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.repository.spi.RepositoryServiceProvider; +import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.UriInfo; @@ -60,7 +61,7 @@ public class RepositoryServiceTest { } @Override - public void serve(HttpServletRequest request, HttpServletResponse response) { + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { } } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 45a0ad5347..4874247785 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -40,9 +40,7 @@ import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; -import sonia.scm.web.ScmGitServlet; -import javax.inject.Provider; import java.io.IOException; import java.util.Collections; import java.util.Set; @@ -76,11 +74,11 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- public GitRepositoryServiceProvider(GitRepositoryHandler handler, - Repository repository, Provider servletProvider) + Repository repository, HttpScmProtocol httpScmProtocol) { this.handler = handler; this.repository = repository; - this.servletProvider = servletProvider; + this.httpScmProtocol = httpScmProtocol; this.context = new GitContext(handler.getDirectory(repository)); } @@ -246,7 +244,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - return Collections.singleton(servletProvider.get()); + return Collections.singleton(httpScmProtocol); } //~--- fields --------------------------------------------------------------- @@ -260,5 +258,5 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private Repository repository; - private final Provider servletProvider; + private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index 2cecb964fe..39ea4f761a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -38,9 +38,7 @@ import com.google.inject.Inject; import sonia.scm.plugin.Extension; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; -import sonia.scm.web.ScmGitServlet; - -import javax.inject.Provider; +import sonia.scm.web.GitScmProtocolProviderWrapper; /** * @@ -56,7 +54,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver //~--- constructors --------------------------------------------------------- @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler, Provider servletProvider) + public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper servletProvider) { this.handler = handler; this.servletProvider = servletProvider; @@ -89,5 +87,5 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private final GitRepositoryHandler handler; - private final Provider servletProvider; + private final HttpScmProtocol servletProvider; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java deleted file mode 100644 index f06fcfcd39..0000000000 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. 2. Redistributions in - * binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. 3. Neither the name of SCM-Manager; - * nor the names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - - -package sonia.scm.web; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.inject.Inject; - -import sonia.scm.Priority; -import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; -import sonia.scm.web.filter.AuthenticationFilter; - -import java.util.Set; - - -/** - * Handles git specific basic authentication. - * - * @author Sebastian Sdorra - */ -@Priority(Filters.PRIORITY_AUTHENTICATION) -@WebElement(value = GitServletModule.PATTERN_GIT) -public class GitBasicAuthenticationFilter extends AuthenticationFilter -{ - - /** - * Constructs a new instance. - * - * @param configuration scm-manager main configuration - * @param webTokenGenerators web token generators - */ - @Inject - public GitBasicAuthenticationFilter(ScmConfiguration configuration, - Set webTokenGenerators) - { - super(configuration, webTokenGenerators); - } -} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index 1f07753f1e..068284188d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -37,25 +37,20 @@ package sonia.scm.web; import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; -import com.google.inject.Singleton; - import org.eclipse.jgit.http.server.GitSmartHttpTools; - import sonia.scm.ClientMessages; +import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; +import sonia.scm.filter.Filters; import sonia.scm.repository.GitUtil; import sonia.scm.repository.RepositoryProvider; import sonia.scm.web.filter.ProviderPermissionFilter; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import sonia.scm.Priority; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; +import java.io.IOException; + +//~--- JDK imports ------------------------------------------------------------ /** * GitPermissionFilter decides if a git request requires write or read privileges. @@ -63,7 +58,7 @@ import sonia.scm.filter.WebElement; * @author Sebastian Sdorra */ @Priority(Filters.PRIORITY_AUTHORIZATION) -@WebElement(value = GitServletModule.PATTERN_GIT) +//@WebElement(value = GitServletModule.PATTERN_GIT) public class GitPermissionFilter extends ProviderPermissionFilter { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java index 76e742a71a..7f04bb3a54 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java @@ -125,8 +125,9 @@ public class GitRepositoryResolver implements RepositoryResolver servletProvider) { + super(servletProvider); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index 94e772123e..9b8d53caf2 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -51,7 +51,7 @@ import sonia.scm.web.lfs.LfsBlobStoreFactory; public class GitServletModule extends ServletModule { - public static final String GIT_PATH = "/git"; + public static final String GIT_PATH = "/repo"; /** Field description */ public static final String PATTERN_GIT = GIT_PATH + "/*"; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java index 5efffec523..261e67c185 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java @@ -44,7 +44,6 @@ import org.slf4j.Logger; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; -import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.util.HttpUtil; import sonia.scm.web.lfs.servlet.LfsServletFactory; @@ -52,9 +51,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; -import java.net.URI; import java.util.regex.Pattern; import static org.eclipse.jgit.lfs.lib.Constants.CONTENT_TYPE_GIT_LFS_JSON; @@ -67,12 +64,12 @@ import static org.slf4j.LoggerFactory.getLogger; * @author Sebastian Sdorra */ @Singleton -public class ScmGitServlet extends GitServlet implements HttpScmProtocol +public class ScmGitServlet extends GitServlet { /** Field description */ public static final Pattern REGEX_GITHTTPBACKEND = Pattern.compile( - "(?x)^/git/(.*/(HEAD|info/refs|objects/(info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\\.(pack|idx))|git-(upload|receive)-pack))$" + "(?x)^/repo/(.*/(HEAD|info/refs|objects/(info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\\.(pack|idx))|git-(upload|receive)-pack))$" ); /** Field description */ @@ -287,17 +284,6 @@ public class ScmGitServlet extends GitServlet implements HttpScmProtocol return false; } - @Override - public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - service(request, response); - } - - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../git/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); - } - - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/servlet/LfsServletFactory.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/servlet/LfsServletFactory.java index 58bdb2fcf1..f4eed34678 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/servlet/LfsServletFactory.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/servlet/LfsServletFactory.java @@ -70,7 +70,7 @@ public class LfsServletFactory { */ @VisibleForTesting static String buildBaseUri(Repository repository, HttpServletRequest request) { - return String.format("%s/git/%s/%s.git/info/lfs/objects/", HttpUtil.getCompleteUrl(request), repository.getNamespace(), repository.getName()); + return String.format("%s/repo/%s/%s.git/info/lfs/objects/", HttpUtil.getCompleteUrl(request), repository.getNamespace(), repository.getName()); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index a8fbf0431e..ae0f259f97 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -59,6 +59,7 @@ import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.EnvList; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -363,7 +364,7 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol } @Override - public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { service(request, response); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index c968763955..44c544bd68 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -49,6 +49,7 @@ import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; @@ -287,7 +288,7 @@ public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol } @Override - public void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { service(request, response); } diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java index 7991cbb596..15536db19a 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java @@ -66,7 +66,7 @@ public class HttpProtocolServlet extends HttpServlet { try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) { requestProvider.get().setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repositoryService.getRepository()); HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); - protocol.serve(req, resp); + protocol.serve(req, resp, getServletConfig()); } catch (RepositoryNotFoundException e) { resp.setStatus(404); } From 5b5bfd342a4bf4b71dc99f80146772525f77d784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 6 Sep 2018 17:39:47 +0200 Subject: [PATCH 06/48] Add POC protocol servlet with delegate to svn and hg --- .../InitializingHttpScmProtocolWrapper.java | 3 ++- .../spi/HgRepositoryServiceProvider.java | 12 +++++++----- .../spi/HgRepositoryServiceResolver.java | 9 ++++++--- .../main/java/sonia/scm/web/HgCGIServlet.java | 13 ------------- .../java/sonia/scm/web/HgPermissionFilter.java | 13 ++++--------- .../scm/web/HgScmProtocolProviderWrapper.java | 15 +++++++++++++++ .../java/sonia/scm/web/HgServletModule.java | 3 --- .../spi/SvnRepositoryServiceProvider.java | 12 +++++++----- .../spi/SvnRepositoryServiceResolver.java | 10 +++++++--- .../scm/web/SvnBasicAuthenticationFilter.java | 18 ++++++------------ .../sonia/scm/web/SvnPermissionFilter.java | 18 ++++++------------ .../scm/web/SvnScmProtocolProviderWrapper.java | 15 +++++++++++++++ .../java/sonia/scm/web/SvnServletModule.java | 5 ++--- .../scm/web/protocol/HttpProtocolServlet.java | 5 ++++- 14 files changed, 81 insertions(+), 70 deletions(-) create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index ad0e7cb513..b06420d9c0 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -28,7 +28,8 @@ public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProto if (!isInitialized) { synchronized (this) { if (!isInitialized) { - delegateProvider.get().init(config); + HttpServlet httpServlet = delegateProvider.get(); + httpServlet.init(config); isInitialized = true; } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 882c5a1c6b..b0499fac9f 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -42,7 +42,6 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; -import sonia.scm.web.HgCGIServlet; import java.io.File; import java.io.IOException; @@ -87,16 +86,17 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider * * * - * + * @param handler * @param hookManager - * @param handler * @param repository + * @param httpScmProtocol */ HgRepositoryServiceProvider(HgRepositoryHandler handler, - HgHookManager hookManager, Repository repository) + HgHookManager hookManager, Repository repository, HttpScmProtocol httpScmProtocol) { this.repository = repository; this.handler = handler; + this.httpScmProtocol = httpScmProtocol; this.repositoryDirectory = handler.getDirectory(repository); this.context = new HgCommandContext(hookManager, handler, repository, repositoryDirectory); @@ -276,7 +276,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - return Collections.singleton(new HgCGIServlet(null, null, null, null, null, null)); + return Collections.singleton(httpScmProtocol); } //~--- fields --------------------------------------------------------------- @@ -292,4 +292,6 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private File repositoryDirectory; + + private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index d322cb8e9f..d32d2f862f 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -36,11 +36,11 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; - import sonia.scm.plugin.Extension; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; +import sonia.scm.web.HgScmProtocolProviderWrapper; /** * @@ -65,10 +65,11 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver */ @Inject public HgRepositoryServiceResolver(HgRepositoryHandler handler, - HgHookManager hookManager) + HgHookManager hookManager, HgScmProtocolProviderWrapper httpScmProtocol) { this.handler = handler; this.hookManager = hookManager; + this.httpScmProtocol = httpScmProtocol; } //~--- methods -------------------------------------------------------------- @@ -89,7 +90,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { provider = new HgRepositoryServiceProvider(handler, hookManager, - repository); + repository, httpScmProtocol); } return provider; @@ -102,4 +103,6 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private HgHookManager hookManager; + + private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index ae0f259f97..3ceb129f3f 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -135,19 +135,6 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol //~--- methods -------------------------------------------------------------- - /** - * Method description - * - * - * @throws ServletException - */ - @Override - public void init() throws ServletException - { - - super.init(); - } - /** * Method description * diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index de2835dd8f..c05f03dc4e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -37,27 +37,22 @@ package sonia.scm.web; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; - -import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; import sonia.scm.repository.RepositoryProvider; import sonia.scm.web.filter.ProviderPermissionFilter; -//~--- JDK imports ------------------------------------------------------------ - +import javax.servlet.http.HttpServletRequest; import java.util.Set; -import javax.servlet.http.HttpServletRequest; +//~--- JDK imports ------------------------------------------------------------ /** * Permission filter for mercurial repositories. * * @author Sebastian Sdorra */ -@Priority(Filters.PRIORITY_AUTHORIZATION) -@WebElement(value = HgServletModule.MAPPING_HG) +//@Priority(Filters.PRIORITY_AUTHORIZATION) +//@WebElement(value = HgServletModule.MAPPING_HG) public class HgPermissionFilter extends ProviderPermissionFilter { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java new file mode 100644 index 0000000000..c67c68024e --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -0,0 +1,15 @@ +package sonia.scm.web; + +import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +@Singleton +public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { + @Inject + public HgScmProtocolProviderWrapper(Provider servletProvider) { + super(servletProvider); + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java index 357995483d..ba9ae3a0b9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java @@ -81,8 +81,5 @@ public class HgServletModule extends ServletModule // bind servlets serve(MAPPING_HOOK).with(HgHookCallbackServlet.class); - - // register hg cgi servlet - serve(MAPPING_HG).with(HgCGIServlet.class); } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java index cbd303a9c6..21d1659bec 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java @@ -41,7 +41,6 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.ScmProtocol; -import sonia.scm.web.SvnDAVServlet; import java.io.IOException; import java.util.Collections; @@ -69,14 +68,15 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider /** * Constructs ... * - * - * @param handler + * @param handler * @param repository + * @param httpScmProtocol */ SvnRepositoryServiceProvider(SvnRepositoryHandler handler, - Repository repository) + Repository repository, HttpScmProtocol httpScmProtocol) { this.repository = repository; + this.httpScmProtocol = httpScmProtocol; this.context = new SvnContext(handler.getDirectory(repository)); } @@ -194,7 +194,7 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider @Override public Set getSupportedProtocols() { - return Collections.singleton(new SvnDAVServlet(null, null, null, null)); + return Collections.singleton(httpScmProtocol); } //~--- fields --------------------------------------------------------------- @@ -204,4 +204,6 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private final Repository repository; + + private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java index d56398083e..48233156c6 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java @@ -35,10 +35,10 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; - import sonia.scm.plugin.Extension; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.web.SvnScmProtocolProviderWrapper; /** * @@ -58,11 +58,13 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver * * * @param handler + * @param httpScmProtocol */ @Inject - public SvnRepositoryServiceResolver(SvnRepositoryHandler handler) + public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper httpScmProtocol) { this.handler = handler; + this.httpScmProtocol = httpScmProtocol; } //~--- methods -------------------------------------------------------------- @@ -82,7 +84,7 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new SvnRepositoryServiceProvider(handler, repository); + provider = new SvnRepositoryServiceProvider(handler, repository, httpScmProtocol); } return provider; @@ -92,4 +94,6 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private SvnRepositoryHandler handler; + + private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java index 1d9581f7c1..b5db32a449 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java @@ -34,30 +34,24 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; - -import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; import sonia.scm.repository.SvnUtil; import sonia.scm.util.HttpUtil; import sonia.scm.web.filter.AuthenticationFilter; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - -import java.util.Set; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ -@Priority(Filters.PRIORITY_AUTHENTICATION) -@WebElement(value = SvnServletModule.PATTERN_SVN) +//@Priority(Filters.PRIORITY_AUTHENTICATION) +//@WebElement(value = SvnServletModule.PATTERN_SVN) public class SvnBasicAuthenticationFilter extends AuthenticationFilter { diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 30ef3e94c0..857e3d6d71 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -37,32 +37,26 @@ package sonia.scm.web; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; - import sonia.scm.ClientMessages; -import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.ScmSvnErrorCode; import sonia.scm.repository.SvnUtil; import sonia.scm.web.filter.ProviderPermissionFilter; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - -import java.util.Set; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ -@Priority(Filters.PRIORITY_AUTHORIZATION) -@WebElement(value = SvnServletModule.PATTERN_SVN) +//@Priority(Filters.PRIORITY_AUTHORIZATION) +//@WebElement(value = SvnServletModule.PATTERN_SVN) public class SvnPermissionFilter extends ProviderPermissionFilter { diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java new file mode 100644 index 0000000000..2f54f57bc8 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -0,0 +1,15 @@ +package sonia.scm.web; + +import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +@Singleton +public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { + @Inject + public SvnScmProtocolProviderWrapper(Provider servletProvider) { + super(servletProvider); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 9b5c8ae556..4dab556c8f 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -70,8 +70,8 @@ public class SvnServletModule extends ServletModule protected void configureServlets() { filter(PATTERN_SVN).through(SvnGZipFilter.class); - filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class); - filter(PATTERN_SVN).through(SvnPermissionFilter.class); +// filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class); +// filter(PATTERN_SVN).through(SvnPermissionFilter.class); bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass()); bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass()); @@ -80,6 +80,5 @@ public class SvnServletModule extends ServletModule parameters.put(PARAMETER_SVN_PARENTPATH, System.getProperty("java.io.tmpdir")); - serve(PATTERN_SVN).with(SvnDAVServlet.class, parameters); } } diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java index 15536db19a..dc25875d5b 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java @@ -25,6 +25,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import static java.lang.Math.max; + @Singleton @WebElement(value = HttpProtocolServlet.PATTERN) @Slf4j @@ -79,7 +81,8 @@ public class HttpProtocolServlet extends HttpServlet { } String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH)); - String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1)); + int endIndex = uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1); + String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, max(endIndex, uri.length())); return new NamespaceAndName(namespace, name); } From 40b9b0da69c2c465013afeea5ca04b7252e3c2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 7 Sep 2018 09:51:23 +0200 Subject: [PATCH 07/48] Initialize svn parent directory for servlet --- .../InitializingHttpScmProtocolWrapper.java | 6 ++- .../java/sonia/scm/web/SvnDAVServlet.java | 2 +- .../web/SvnScmProtocolProviderWrapper.java | 45 +++++++++++++++++++ .../java/sonia/scm/web/SvnServletModule.java | 8 ---- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index b06420d9c0..0e0e32dbf1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -29,7 +29,7 @@ public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProto synchronized (this) { if (!isInitialized) { HttpServlet httpServlet = delegateProvider.get(); - httpServlet.init(config); + initializeServlet(config, httpServlet); isInitialized = true; } } @@ -37,6 +37,10 @@ public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProto delegateProvider.get().service(request, response); } + protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { + httpServlet.init(config); + } + @Override public String getUrl(Repository repository, UriInfo uriInfo) { diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index 44c544bd68..0a2a63da46 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -294,7 +294,7 @@ public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol @Override public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../svn/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 2f54f57bc8..5544bf796e 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -5,6 +5,13 @@ import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import java.util.Enumeration; + +import static sonia.scm.web.SvnServletModule.PARAMETER_SVN_PARENTPATH; @Singleton public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @@ -12,4 +19,42 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr public SvnScmProtocolProviderWrapper(Provider servletProvider) { super(servletProvider); } + + @Override + protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { + + super.initializeServlet(new X(config), httpServlet); + } + + private static class X implements ServletConfig { + + private final ServletConfig originalConfig; + + private X(ServletConfig originalConfig) { + this.originalConfig = originalConfig; + } + + @Override + public String getServletName() { + return originalConfig.getServletName(); + } + + @Override + public ServletContext getServletContext() { + return originalConfig.getServletContext(); + } + + @Override + public String getInitParameter(String key) { + if (PARAMETER_SVN_PARENTPATH.equals(key)) { + return System.getProperty("java.io.tmpdir"); + } + return originalConfig.getInitParameter(key); + } + + @Override + public Enumeration getInitParameterNames() { + return originalConfig.getInitParameterNames(); + } + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 4dab556c8f..9b9dc0bcb0 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -41,9 +41,6 @@ import sonia.scm.api.v2.resources.SvnConfigDtoToSvnConfigMapper; import sonia.scm.api.v2.resources.SvnConfigToSvnConfigDtoMapper; import sonia.scm.plugin.Extension; -import java.util.HashMap; -import java.util.Map; - //~--- JDK imports ------------------------------------------------------------ /** @@ -75,10 +72,5 @@ public class SvnServletModule extends ServletModule bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass()); bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass()); - - Map parameters = new HashMap(); - - parameters.put(PARAMETER_SVN_PARENTPATH, - System.getProperty("java.io.tmpdir")); } } From eff51c3b378182e698eeef8c9998257fa7b649e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 08:34:47 +0200 Subject: [PATCH 08/48] Remove not thrown exceptions from declaration --- .../src/main/java/sonia/scm/web/HgCGIServlet.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index 3ceb129f3f..03acc3bc29 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -148,7 +148,6 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol @Override protected void service(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { Repository repository = repositoryProvider.get(); @@ -351,7 +350,7 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol } @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { service(request, response); } From 9198cac0a554853ed4607d474d6ea08a47bed3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 08:36:05 +0200 Subject: [PATCH 09/48] Correct usage of RepositoryNotFoundException --- .../sonia/scm/repository/RepositoryNotFoundException.java | 4 ++++ .../sonia/scm/repository/api/RepositoryServiceFactory.java | 4 +--- .../sonia/scm/api/v2/resources/PermissionRootResource.java | 5 +++-- .../src/main/java/sonia/scm/repository/HealthChecker.java | 3 +-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java index 070221117a..1208596348 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java @@ -61,4 +61,8 @@ public class RepositoryNotFoundException extends NotFoundException public RepositoryNotFoundException(String repositoryId) { super("repository", repositoryId); } + + public RepositoryNotFoundException(NamespaceAndName namespaceAndName) { + super("repository", namespaceAndName.toString()); + } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java index 627e57a797..33f57d4524 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java @@ -208,9 +208,7 @@ public final class RepositoryServiceFactory if (repository == null) { - String msg = "could not find a repository with namespace/name " + namespaceAndName; - - throw new RepositoryNotFoundException(msg); + throw new RepositoryNotFoundException(namespaceAndName); } return create(repository); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionRootResource.java index 2b53192542..7f15120357 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionRootResource.java @@ -210,8 +210,9 @@ public class PermissionRootResource { * @throws RepositoryNotFoundException if the repository does not exists */ private Repository load(String namespace, String name) throws RepositoryNotFoundException { - return Optional.ofNullable(manager.get(new NamespaceAndName(namespace, name))) - .orElseThrow(() -> new RepositoryNotFoundException(name)); + NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name); + return Optional.ofNullable(manager.get(namespaceAndName)) + .orElseThrow(() -> new RepositoryNotFoundException(namespaceAndName)); } /** diff --git a/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java b/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java index 0d27c6d250..52dea4223b 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java @@ -61,8 +61,7 @@ public final class HealthChecker { Repository repository = repositoryManager.get(id); if (repository == null) { - throw new RepositoryNotFoundException( - "could not find repository with id ".concat(id)); + throw new RepositoryNotFoundException(id); } doCheck(repository); From 6d659b8ac104740df4dce2a0c773ddabaa6ef307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 08:37:31 +0200 Subject: [PATCH 10/48] Correct extraction of namespace and name from path --- .../scm/web/protocol/HttpProtocolServlet.java | 60 ++++----- .../NamespaceAndNameFromPathExtractor.java | 33 +++++ .../web/protocol/HttpProtocolServletTest.java | 124 ++++++++++++++++++ ...NamespaceAndNameFromPathExtractorTest.java | 59 +++++++++ 4 files changed, 241 insertions(+), 35 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java create mode 100644 scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java create mode 100644 scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java index dc25875d5b..d314628438 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java @@ -1,31 +1,27 @@ package sonia.scm.web.protocol; import com.google.inject.Inject; -import com.google.inject.Provider; import com.google.inject.Singleton; import lombok.extern.slf4j.Slf4j; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.subject.Subject; +import org.apache.http.HttpStatus; import sonia.scm.PushStateDispatcher; import sonia.scm.filter.WebElement; import sonia.scm.repository.DefaultRepositoryProvider; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.RepositoryNotFoundException; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.spi.HttpScmProtocol; -import sonia.scm.util.HttpUtil; import sonia.scm.web.UserAgent; import sonia.scm.web.UserAgentParser; +import javax.inject.Provider; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; - -import static java.lang.Math.max; +import java.util.Optional; @Singleton @WebElement(value = HttpProtocolServlet.PATTERN) @@ -34,7 +30,6 @@ public class HttpProtocolServlet extends HttpServlet { public static final String PATTERN = "/repo/*"; - private final RepositoryProvider repositoryProvider; private final RepositoryServiceFactory serviceFactory; private final Provider requestProvider; @@ -42,48 +37,43 @@ public class HttpProtocolServlet extends HttpServlet { private final PushStateDispatcher dispatcher; private final UserAgentParser userAgentParser; + private final NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor; + @Inject - public HttpProtocolServlet(RepositoryProvider repositoryProvider, RepositoryServiceFactory serviceFactory, Provider requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser) { - this.repositoryProvider = repositoryProvider; + public HttpProtocolServlet(RepositoryServiceFactory serviceFactory, Provider requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser, NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor) { this.serviceFactory = serviceFactory; this.requestProvider = requestProvider; this.dispatcher = dispatcher; this.userAgentParser = userAgentParser; + this.namespaceAndNameFromPathExtractor = namespaceAndNameFromPathExtractor; } @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Subject subject = SecurityUtils.getSubject(); - - - UserAgent userAgent = userAgentParser.parse(req); + protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + UserAgent userAgent = userAgentParser.parse(request); if (userAgent.isBrowser()) { log.trace("dispatch browser request for user agent {}", userAgent); - dispatcher.dispatch(req, resp, req.getRequestURI()); + dispatcher.dispatch(request, response, request.getRequestURI()); } else { - - - String pathInfo = req.getPathInfo(); - NamespaceAndName namespaceAndName = fromUri(pathInfo); - try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) { - requestProvider.get().setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repositoryService.getRepository()); - HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); - protocol.serve(req, resp, getServletConfig()); - } catch (RepositoryNotFoundException e) { - resp.setStatus(404); + String pathInfo = request.getPathInfo(); + Optional namespaceAndName = namespaceAndNameFromPathExtractor.fromUri(pathInfo); + if (namespaceAndName.isPresent()) { + service(request, response, namespaceAndName.get()); + } else { + log.debug("namespace and name not found in request path {}", pathInfo); + response.setStatus(HttpStatus.SC_BAD_REQUEST); } } } - private NamespaceAndName fromUri(String uri) { - if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) { - uri = uri.substring(1); + private void service(HttpServletRequest req, HttpServletResponse resp, NamespaceAndName namespaceAndName) throws IOException, ServletException { + try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) { + requestProvider.get().setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repositoryService.getRepository()); + HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); + protocol.serve(req, resp, getServletConfig()); + } catch (RepositoryNotFoundException e) { + log.debug("Repository not found for namespace and name {}", namespaceAndName, e); + resp.setStatus(HttpStatus.SC_NOT_FOUND); } - - String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH)); - int endIndex = uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1); - String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, max(endIndex, uri.length())); - - return new NamespaceAndName(namespace, name); } } diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java new file mode 100644 index 0000000000..b4315bc6ac --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java @@ -0,0 +1,33 @@ +package sonia.scm.web.protocol; + +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.util.HttpUtil; + +import java.util.Optional; + +import static java.util.Optional.empty; +import static java.util.Optional.of; + +class NamespaceAndNameFromPathExtractor { + Optional fromUri(String uri) { + if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) { + uri = uri.substring(1); + } + + int endOfNamespace = uri.indexOf(HttpUtil.SEPARATOR_PATH); + if (endOfNamespace < 1) { + return empty(); + } + + String namespace = uri.substring(0, endOfNamespace); + int nameSeparatorIndex = uri.indexOf(HttpUtil.SEPARATOR_PATH, endOfNamespace + 1); + int nameIndex = nameSeparatorIndex > 0 ? nameSeparatorIndex : uri.length(); + if (nameIndex == endOfNamespace + 1) { + return empty(); + } + + String name = uri.substring(endOfNamespace + 1, nameIndex); + + return of(new NamespaceAndName(namespace, name)); + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java b/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java new file mode 100644 index 0000000000..2d4f6b639b --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java @@ -0,0 +1,124 @@ +package sonia.scm.web.protocol; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import sonia.scm.PushStateDispatcher; +import sonia.scm.repository.DefaultRepositoryProvider; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryNotFoundException; +import sonia.scm.repository.api.RepositoryService; +import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.repository.spi.HttpScmProtocol; +import sonia.scm.web.UserAgent; +import sonia.scm.web.UserAgentParser; + +import javax.inject.Provider; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Optional; + +import static java.util.Optional.of; +import static org.mockito.AdditionalMatchers.not; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +public class HttpProtocolServletTest { + + private static final NamespaceAndName EXISTING_REPO = new NamespaceAndName("space", "repo"); + + @Mock + private RepositoryServiceFactory serviceFactory; + @Mock + private HttpServletRequest httpServletRequest; + @Mock + private PushStateDispatcher dispatcher; + @Mock + private UserAgentParser userAgentParser; + @Mock + private NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor; + @Mock + private Provider requestProvider; + + @InjectMocks + private HttpProtocolServlet servlet; + + @Mock + private RepositoryService repositoryService; + @Mock + private UserAgent userAgent; + + @Mock + private HttpServletRequest request; + @Mock + private HttpServletResponse response; + @Mock + private HttpScmProtocol protocol; + + @Before + public void init() throws RepositoryNotFoundException { + initMocks(this); + when(userAgentParser.parse(request)).thenReturn(userAgent); + when(userAgent.isBrowser()).thenReturn(false); + when(serviceFactory.create(not(eq(EXISTING_REPO)))).thenThrow(RepositoryNotFoundException.class); + when(serviceFactory.create(EXISTING_REPO)).thenReturn(repositoryService); + when(requestProvider.get()).thenReturn(httpServletRequest); + } + + @Test + public void shouldDispatchBrowserRequests() throws ServletException, IOException { + when(userAgent.isBrowser()).thenReturn(true); + when(request.getRequestURI()).thenReturn("uri"); + + servlet.service(request, response); + + verify(dispatcher).dispatch(request, response, "uri"); + } + + @Test + public void shouldHandleBadPaths() throws IOException, ServletException { + when(request.getPathInfo()).thenReturn("/space/name"); + when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(Optional.empty()); + + servlet.service(request, response); + + verify(response).setStatus(400); + } + + @Test + public void shouldHandleNotExistingRepository() throws RepositoryNotFoundException, IOException, ServletException { + when(request.getPathInfo()).thenReturn("/space/name"); + NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name"); + when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(of(namespaceAndName)); + doThrow(new RepositoryNotFoundException(namespaceAndName)).when(serviceFactory).create(namespaceAndName); + + servlet.service(request, response); + + verify(response).setStatus(404); + } + + @Test + public void shouldDelegateToProvider() throws RepositoryNotFoundException, IOException, ServletException { + when(request.getPathInfo()).thenReturn("/space/name"); + NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name"); + when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(of(namespaceAndName)); + doReturn(repositoryService).when(serviceFactory).create(namespaceAndName); + Repository repository = new Repository(); + when(repositoryService.getRepository()).thenReturn(repository); + when(repositoryService.getProtocol(HttpScmProtocol.class)).thenReturn(protocol); + + servlet.service(request, response); + + verify(httpServletRequest).setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repository); + verify(protocol).serve(request, response, null); + verify(repositoryService).close(); + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java new file mode 100644 index 0000000000..be26ac89db --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java @@ -0,0 +1,59 @@ +package sonia.scm.web.protocol; + +import org.junit.jupiter.api.DynamicNode; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import sonia.scm.repository.NamespaceAndName; + +import java.util.Optional; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +public class NamespaceAndNameFromPathExtractorTest { + @TestFactory + Stream shouldExtractCorrectNamespaceAndName() { + return Stream.of( + "/space/repo", + "/space/repo/", + "/space/repo/here", + "/space/repo/here/there", + "space/repo", + "space/repo/", + "space/repo/here/there" + ).map(this::createCorrectTest); + } + + private DynamicTest createCorrectTest(String path) { + return dynamicTest( + "should extract correct namespace and name for path " + path, + () -> { + Optional namespaceAndName = new NamespaceAndNameFromPathExtractor().fromUri(path); + + assertThat(namespaceAndName.get()).isEqualTo(new NamespaceAndName("space", "repo")); + } + ); + } + + @TestFactory + Stream shouldHandleMissingParts() { + return Stream.of( + "", + "/", + "/space", + "/space/" + ).map(this::createFailureTest); + } + + private DynamicTest createFailureTest(String path) { + return dynamicTest( + "should not fail for wrong path " + path, + () -> { + Optional namespaceAndName = new NamespaceAndNameFromPathExtractor().fromUri(path); + + assertThat(namespaceAndName.isPresent()).isFalse(); + } + ); + } +} From 50a4133dff68ca2e350ca0ce346f228f3f092813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 10:08:51 +0200 Subject: [PATCH 11/48] Remove old type dependant repo uri functions --- .../scm/repository/RepositoryManager.java | 24 ------- .../RepositoryManagerDecorator.java | 29 --------- .../spi/DefaultHttpScmProtocol.java | 8 --- .../scm/repository/spi/HttpScmProtocol.java | 8 +++ .../InitializingHttpScmProtocolWrapper.java | 10 --- .../repository/api/RepositoryServiceTest.java | 16 ----- .../lfs/servlet/LfsServletFactoryTest.java | 10 ++- .../main/java/sonia/scm/web/HgCGIServlet.java | 7 --- .../java/sonia/scm/web/SvnDAVServlet.java | 8 --- .../scm/api/v2/resources/ResourceLinks.java | 1 + .../repository/DefaultRepositoryManager.java | 27 -------- .../DefaultRepositoryManagerTest.java | 63 ------------------- 12 files changed, 13 insertions(+), 198 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java index 2c4d958d8d..1e2fdccf42 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java @@ -38,7 +38,6 @@ package sonia.scm.repository; import sonia.scm.AlreadyExistsException; import sonia.scm.TypeManager; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Collection; @@ -99,29 +98,6 @@ public interface RepositoryManager */ public Collection getConfiguredTypes(); - /** - * Returns the {@link Repository} associated to the request uri. - * - * - * @param request the current http request - * - * @return associated to the request uri - * @since 1.9 - */ - public Repository getFromRequest(HttpServletRequest request); - - /** - * Returns the {@link Repository} associated to the request uri. - * - * - * - * @param uri request uri without context path - * - * @return associated to the request uri - * @since 1.9 - */ - public Repository getFromUri(String uri); - /** * Returns a {@link RepositoryHandler} by the given type (hg, git, svn ...). * diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java index aa4117af34..87df960da7 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java @@ -39,7 +39,6 @@ import sonia.scm.AlreadyExistsException; import sonia.scm.ManagerDecorator; import sonia.scm.Type; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Collection; @@ -120,34 +119,6 @@ public class RepositoryManagerDecorator return decorated; } - /** - * {@inheritDoc} - * - * - * @param request - * - * @return - */ - @Override - public Repository getFromRequest(HttpServletRequest request) - { - return decorated.getFromRequest(request); - } - - /** - * {@inheritDoc} - * - * - * @param uri - * - * @return - */ - @Override - public Repository getFromUri(String uri) - { - return decorated.getFromUri(uri); - } - /** * {@inheritDoc} * diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java index 223be7aca8..9aaf1dfb4b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java @@ -2,9 +2,6 @@ package sonia.scm.repository.spi; import sonia.scm.repository.Repository; -import javax.ws.rs.core.UriInfo; -import java.net.URI; - public abstract class DefaultHttpScmProtocol implements HttpScmProtocol { private final Repository repository; @@ -12,9 +9,4 @@ public abstract class DefaultHttpScmProtocol implements HttpScmProtocol { protected DefaultHttpScmProtocol(Repository repository) { this.repository = repository; } - - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../" + this.repository.getType() + "/" + this.repository.getNamespace() + "/" + this.repository.getName())).toASCIIString(); - } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index c19205c1e7..fed9c00cdc 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -1,12 +1,15 @@ package sonia.scm.repository.spi; +import sonia.scm.repository.Repository; import sonia.scm.repository.api.ScmProtocol; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; import java.io.IOException; +import java.net.URI; public interface HttpScmProtocol extends ScmProtocol { @Override @@ -14,5 +17,10 @@ public interface HttpScmProtocol extends ScmProtocol { return "http"; } + @Override + default String getUrl(Repository repository, UriInfo uriInfo) { + return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + } + void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 0e0e32dbf1..9c26c0905a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,16 +1,12 @@ package sonia.scm.repository.spi; -import sonia.scm.repository.Repository; - import javax.inject.Provider; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; -import java.net.URI; public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProtocol { @@ -40,10 +36,4 @@ public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProto protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { httpServlet.init(config); } - - - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); - } } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index 8d37c0e187..b363516a67 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -8,7 +8,6 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.util.Collection; import java.util.Collections; @@ -33,16 +32,6 @@ public class RepositoryServiceTest { assertThat(sizeOf(supportedProtocols)).isEqualTo(1); } - @Test - public void shouldFindProtocolFromProvider() { - when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol())); - - RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); - HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); - - assertThat(protocol.getUrl(repository, null)).isEqualTo("dummy"); - } - @Test public void shouldFailForUnknownProtocol() { when(provider.getSupportedProtocols()).thenReturn(Collections.emptySet()); @@ -55,11 +44,6 @@ public class RepositoryServiceTest { } private static class DummyHttpProtocol implements HttpScmProtocol { - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return "dummy"; - } - @Override public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java index f6f5803bb7..09a431ea43 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java @@ -23,12 +23,12 @@ public class LfsServletFactoryTest { String repositoryName = "git-lfs-demo"; String result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryNamespace, repositoryName), RequestWithUri(repositoryName, true)); - assertThat(result, is(equalTo("http://localhost:8081/scm/git/space/git-lfs-demo.git/info/lfs/objects/"))); + assertThat(result, is(equalTo("http://localhost:8081/scm/repo/space/git-lfs-demo.git/info/lfs/objects/"))); //result will be with dot-git suffix, ide result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryNamespace, repositoryName), RequestWithUri(repositoryName, false)); - assertThat(result, is(equalTo("http://localhost:8081/scm/git/space/git-lfs-demo.git/info/lfs/objects/"))); + assertThat(result, is(equalTo("http://localhost:8081/scm/repo/space/git-lfs-demo.git/info/lfs/objects/"))); } private HttpServletRequest RequestWithUri(String repositoryName, boolean withDotGitSuffix) { @@ -44,12 +44,10 @@ public class LfsServletFactoryTest { //build from valid live request data when(mockedRequest.getRequestURL()).thenReturn( - new StringBuffer(String.format("http://localhost:8081/scm/git/%s%s/info/lfs/objects/batch", repositoryName, suffix))); - when(mockedRequest.getRequestURI()).thenReturn(String.format("/scm/git/%s%s/info/lfs/objects/batch", repositoryName, suffix)); + new StringBuffer(String.format("http://localhost:8081/scm/repo/%s%s/info/lfs/objects/batch", repositoryName, suffix))); + when(mockedRequest.getRequestURI()).thenReturn(String.format("/scm/repo/%s%s/info/lfs/objects/batch", repositoryName, suffix)); when(mockedRequest.getContextPath()).thenReturn("/scm"); return mockedRequest; } - - } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index 03acc3bc29..b124c9d3af 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -65,10 +65,8 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import javax.ws.rs.core.UriInfo; import java.io.File; import java.io.IOException; -import java.net.URI; import java.util.Base64; import java.util.Enumeration; @@ -354,11 +352,6 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol service(request, response); } - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../hg/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); - } - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index 0a2a63da46..0dda4306c6 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -54,9 +54,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; -import java.net.URI; //~--- JDK imports ------------------------------------------------------------ @@ -292,12 +290,6 @@ public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol service(request, response); } - @Override - public String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); - } - - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java index 5fe2a2cfd2..11258745a8 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java @@ -4,6 +4,7 @@ import sonia.scm.repository.NamespaceAndName; import javax.inject.Inject; import javax.ws.rs.core.UriInfo; +import java.net.URI; class ResourceLinks { diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 06f92f7bec..8638c7e4e8 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -52,11 +52,9 @@ import sonia.scm.config.ScmConfiguration; import sonia.scm.security.KeyGenerator; import sonia.scm.util.AssertUtil; import sonia.scm.util.CollectionAppender; -import sonia.scm.util.HttpUtil; import sonia.scm.util.IOUtil; import sonia.scm.util.Util; -import javax.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -315,31 +313,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return validTypes; } - @Override - public Repository getFromRequest(HttpServletRequest request) { - AssertUtil.assertIsNotNull(request); - - return getFromUri(HttpUtil.getStrippedURI(request)); - } - - @Override - public Repository getFromUri(String uri) { - AssertUtil.assertIsNotEmpty(uri); - - if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) { - uri = uri.substring(1); - } - - Repository repository = null; - - String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH)); - String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1)); - - repository = get(new NamespaceAndName(namespace, name)); - - return repository; - } - @Override public RepositoryHandler getHandler(String type) { return handlerMap.get(type); diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index efd3f673b0..d85ce12014 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -383,69 +383,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase { assertEquals("default_namespace", repository.getNamespace()); } - @Test - public void getRepositoryFromRequestUri_withoutLeadingSlash() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertEquals("scm-test", m.getFromUri("hg/namespace/scm-test").getName()); - assertEquals("namespace", m.getFromUri("hg/namespace/scm-test").getNamespace()); - } - - @Test - public void getRepositoryFromRequestUri_withLeadingSlash() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertEquals("scm-test", m.getFromUri("/hg/namespace/scm-test").getName()); - assertEquals("namespace", m.getFromUri("/hg/namespace/scm-test").getNamespace()); - } - - @Test - public void getRepositoryFromRequestUri_withPartialName() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertEquals("scm", m.getFromUri("hg/namespace/scm").getName()); - assertEquals("namespace", m.getFromUri("hg/namespace/scm").getNamespace()); - } - - @Test - public void getRepositoryFromRequestUri_withTrailingFilePath() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertEquals("test-1", m.getFromUri("/git/namespace/test-1/ka/some/path").getName()); - } - - @Test - public void getRepositoryFromRequestUri_forNotExistingRepositoryName() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertNull(m.getFromUri("/git/namespace/test-3/ka/some/path")); - } - - @Test - public void getRepositoryFromRequestUri_forWrongNamespace() throws AlreadyExistsException { - RepositoryManager m = createManager(); - m.init(contextProvider); - - createUriTestRepositories(m); - - assertNull(m.getFromUri("/git/other/other/test-2")); - } - @Test public void shouldSetNamespace() throws AlreadyExistsException { Repository repository = new Repository(null, "hg", null, "scm"); From 6bc41cee0ab3a4e1d0af6e3e344bede9a2622164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 11:03:10 +0200 Subject: [PATCH 12/48] Handle git urls with trailing .git suffix correctly --- .../java/sonia/scm/api/v2/resources/RepositoryDto.java | 2 +- .../web/protocol/NamespaceAndNameFromPathExtractor.java | 7 ++++++- .../protocol/NamespaceAndNameFromPathExtractorTest.java | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java index c597e12d4f..ddfe432d73 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java @@ -24,7 +24,7 @@ public class RepositoryDto extends HalRepresentation { @JsonInclude(JsonInclude.Include.NON_NULL) private Instant lastModified; private String namespace; - @Pattern(regexp = "(?!^\\.\\.$)(?!^\\.$)(?!.*[\\\\\\[\\]])^[A-z0-9\\.][A-z0-9\\.\\-_/]*$") + @Pattern(regexp = "^[A-z0-9\\-_]+$") private String name; private boolean archived = false; @NotEmpty diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java index b4315bc6ac..8cbdadf942 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java @@ -28,6 +28,11 @@ class NamespaceAndNameFromPathExtractor { String name = uri.substring(endOfNamespace + 1, nameIndex); - return of(new NamespaceAndName(namespace, name)); + int nameDotIndex = name.indexOf('.'); + if (nameDotIndex >= 0) { + return of(new NamespaceAndName(namespace, name.substring(0, nameDotIndex))); + } else { + return of(new NamespaceAndName(namespace, name)); + } } } diff --git a/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java index be26ac89db..3018870e7d 100644 --- a/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java +++ b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java @@ -25,6 +25,15 @@ public class NamespaceAndNameFromPathExtractorTest { ).map(this::createCorrectTest); } + @TestFactory + Stream shouldHandleTrailingDotSomethings() { + return Stream.of( + "/space/repo.git", + "/space/repo.and.more", + "/space/repo." + ).map(this::createCorrectTest); + } + private DynamicTest createCorrectTest(String path) { return dynamicTest( "should extract correct namespace and name for path " + path, From 8c675f5dd873bc35e45ff9a7a68ed2b8b39d3730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 11:59:21 +0200 Subject: [PATCH 13/48] Compute base url in webapp --- .../src/main/java/sonia/scm/repository/api/ScmProtocol.java | 4 ++-- .../main/java/sonia/scm/repository/spi/HttpScmProtocol.java | 5 ++--- scm-webapp/src/main/java/sonia/scm/ScmServletModule.java | 3 ++- .../api/v2/resources/RepositoryToRepositoryDtoMapper.java | 2 +- .../java/sonia/scm/web/protocol/HttpProtocolServlet.java | 3 ++- .../java/sonia/scm/api/v2/resources/MockScmProtocol.java | 4 ++-- .../scm/api/v2/resources/RepositoryRootResourceTest.java | 5 +++++ .../v2/resources/RepositoryToRepositoryDtoMapperTest.java | 5 +++++ 8 files changed, 21 insertions(+), 10 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java index 8d44ec19ad..0d9e1ae88e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -2,7 +2,7 @@ package sonia.scm.repository.api; import sonia.scm.repository.Repository; -import javax.ws.rs.core.UriInfo; +import java.net.URI; /** * An ScmProtocol represents a concrete protocol provided by the SCM-Manager instance @@ -19,5 +19,5 @@ public interface ScmProtocol { /** * The URL to access the repository providing this protocol. */ - String getUrl(Repository repository, UriInfo uriInfo); + String getUrl(Repository repository, URI baseUri); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index fed9c00cdc..69952802fd 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -7,7 +7,6 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.net.URI; @@ -18,8 +17,8 @@ public interface HttpScmProtocol extends ScmProtocol { } @Override - default String getUrl(Repository repository, UriInfo uriInfo) { - return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + default String getUrl(Repository repository, URI baseUri) { + return baseUri.resolve(URI.create("/repo" + "/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); } void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 2ea17e9da3..14fb8552f9 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -114,6 +114,7 @@ import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.DefaultCGIExecutorFactory; import sonia.scm.web.filter.AuthenticationFilter; import sonia.scm.web.filter.LoggingFilter; +import sonia.scm.web.protocol.HttpProtocolServlet; import sonia.scm.web.security.AdministrationContext; import sonia.scm.web.security.DefaultAdministrationContext; @@ -322,7 +323,7 @@ public class ScmServletModule extends ServletModule bind(TemplateEngineFactory.class); bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class); - filter("/repo/*").through(AuthenticationFilter.class); + filter(HttpProtocolServlet.PATTERN).through(AuthenticationFilter.class); // bind events // bind(LastModifiedUpdateListener.class); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index bc0073506e..62d7abedf7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -67,6 +67,6 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Mon, 10 Sep 2018 14:00:13 +0200 Subject: [PATCH 14/48] Inject repository from service provider --- .../sonia/scm/repository/api/ScmProtocol.java | 4 +- .../spi/DefaultHttpScmProtocol.java | 12 ------ .../scm/repository/spi/HttpScmProtocol.java | 17 +++++--- .../InitializingHttpScmProtocolWrapper.java | 43 ++++++++++++------- .../repository/api/RepositoryServiceTest.java | 8 +++- .../spi/GitRepositoryServiceResolver.java | 8 ++-- .../spi/HgRepositoryServiceProvider.java | 10 ----- .../spi/HgRepositoryServiceResolver.java | 8 ++-- .../main/java/sonia/scm/web/HgCGIServlet.java | 5 +-- .../spi/SvnRepositoryServiceResolver.java | 10 ++--- .../java/sonia/scm/web/SvnDAVServlet.java | 5 +-- .../RepositoryToRepositoryDtoMapper.java | 2 +- .../scm/api/v2/resources/MockScmProtocol.java | 3 +- 13 files changed, 66 insertions(+), 69 deletions(-) delete mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java index 0d9e1ae88e..b865d6e55b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -1,7 +1,5 @@ package sonia.scm.repository.api; -import sonia.scm.repository.Repository; - import java.net.URI; /** @@ -19,5 +17,5 @@ public interface ScmProtocol { /** * The URL to access the repository providing this protocol. */ - String getUrl(Repository repository, URI baseUri); + String getUrl(URI baseUri); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java deleted file mode 100644 index 9aaf1dfb4b..0000000000 --- a/scm-core/src/main/java/sonia/scm/repository/spi/DefaultHttpScmProtocol.java +++ /dev/null @@ -1,12 +0,0 @@ -package sonia.scm.repository.spi; - -import sonia.scm.repository.Repository; - -public abstract class DefaultHttpScmProtocol implements HttpScmProtocol { - - private final Repository repository; - - protected DefaultHttpScmProtocol(Repository repository) { - this.repository = repository; - } -} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index 69952802fd..310b663d5d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -10,16 +10,23 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URI; -public interface HttpScmProtocol extends ScmProtocol { +public abstract class HttpScmProtocol implements ScmProtocol { + + private final Repository repository; + + public HttpScmProtocol(Repository repository) { + this.repository = repository; + } + @Override - default String getType() { + public String getType() { return "http"; } @Override - default String getUrl(Repository repository, URI baseUri) { - return baseUri.resolve(URI.create("/repo" + "/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + public String getUrl(URI baseUri) { + return baseUri.resolve(URI.create("repo" + "/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); } - void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; + public abstract void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 9c26c0905a..b83386a380 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,5 +1,7 @@ package sonia.scm.repository.spi; +import sonia.scm.repository.Repository; + import javax.inject.Provider; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -8,7 +10,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProtocol { +public abstract class InitializingHttpScmProtocolWrapper { private final Provider delegateProvider; @@ -19,21 +21,32 @@ public abstract class InitializingHttpScmProtocolWrapper implements HttpScmProto this.delegateProvider = delegateProvider; } - @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { - if (!isInitialized) { - synchronized (this) { - if (!isInitialized) { - HttpServlet httpServlet = delegateProvider.get(); - initializeServlet(config, httpServlet); - isInitialized = true; - } - } - } - delegateProvider.get().service(request, response); - } - protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { httpServlet.init(config); } + + public HttpScmProtocol get(Repository repository) { + return new ProtocolWrapper(repository); + } + + private class ProtocolWrapper extends HttpScmProtocol { + + public ProtocolWrapper(Repository repository) { + super(repository); + } + + @Override + public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { + if (!isInitialized) { + synchronized (InitializingHttpScmProtocolWrapper.this) { + if (!isInitialized) { + HttpServlet httpServlet = delegateProvider.get(); + initializeServlet(config, httpServlet); + isInitialized = true; + } + } + } + delegateProvider.get().service(request, response); + } + } } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index b363516a67..0f7914b4b0 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -24,7 +24,7 @@ public class RepositoryServiceTest { @Test public void shouldReturnProtocolsFromProvider() { - when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol())); + when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol(repository))); RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); Collection supportedProtocols = repositoryService.getSupportedProtocols(); @@ -43,7 +43,11 @@ public class RepositoryServiceTest { }); } - private static class DummyHttpProtocol implements HttpScmProtocol { + private static class DummyHttpProtocol extends HttpScmProtocol { + public DummyHttpProtocol(Repository repository) { + super(repository); + } + @Override public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index 39ea4f761a..654b586088 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -54,10 +54,10 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver //~--- constructors --------------------------------------------------------- @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper servletProvider) + public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper providerWrapper) { this.handler = handler; - this.servletProvider = servletProvider; + this.providerWrapper = providerWrapper; } //~--- methods -------------------------------------------------------------- @@ -77,7 +77,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new GitRepositoryServiceProvider(handler, repository, servletProvider); + provider = new GitRepositoryServiceProvider(handler, repository, providerWrapper.get(repository)); } return provider; @@ -87,5 +87,5 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private final GitRepositoryHandler handler; - private final HttpScmProtocol servletProvider; + private final GitScmProtocolProviderWrapper providerWrapper; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index b0499fac9f..1fc837029c 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -81,16 +81,6 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * - * - * @param handler - * @param hookManager - * @param repository - * @param httpScmProtocol - */ HgRepositoryServiceProvider(HgRepositoryHandler handler, HgHookManager hookManager, Repository repository, HttpScmProtocol httpScmProtocol) { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index d32d2f862f..08db6d1dbd 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -65,11 +65,11 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver */ @Inject public HgRepositoryServiceResolver(HgRepositoryHandler handler, - HgHookManager hookManager, HgScmProtocolProviderWrapper httpScmProtocol) + HgHookManager hookManager, HgScmProtocolProviderWrapper providerWrapper) { this.handler = handler; this.hookManager = hookManager; - this.httpScmProtocol = httpScmProtocol; + this.providerWrapper = providerWrapper; } //~--- methods -------------------------------------------------------------- @@ -90,7 +90,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { provider = new HgRepositoryServiceProvider(handler, hookManager, - repository, httpScmProtocol); + repository, providerWrapper.get(repository)); } return provider; @@ -104,5 +104,5 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private HgHookManager hookManager; - private final HttpScmProtocol httpScmProtocol; + private final HgScmProtocolProviderWrapper providerWrapper; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index b124c9d3af..f8fabbc040 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -51,7 +51,6 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; -import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.security.CipherUtil; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; @@ -77,7 +76,7 @@ import java.util.Enumeration; * @author Sebastian Sdorra */ @Singleton -public class HgCGIServlet extends HttpServlet implements HttpScmProtocol +public class HgCGIServlet extends HttpServlet { /** Field description */ @@ -347,7 +346,7 @@ public class HgCGIServlet extends HttpServlet implements HttpScmProtocol return python; } - @Override +// @Override public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { service(request, response); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java index 48233156c6..eb52ba55f0 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java @@ -58,13 +58,13 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver * * * @param handler - * @param httpScmProtocol + * @param protocolWrapper */ @Inject - public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper httpScmProtocol) + public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper protocolWrapper) { this.handler = handler; - this.httpScmProtocol = httpScmProtocol; + this.protocolWrapper = protocolWrapper; } //~--- methods -------------------------------------------------------------- @@ -84,7 +84,7 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new SvnRepositoryServiceProvider(handler, repository, httpScmProtocol); + provider = new SvnRepositoryServiceProvider(handler, repository, protocolWrapper.get(repository)); } return provider; @@ -95,5 +95,5 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver /** Field description */ private SvnRepositoryHandler handler; - private final HttpScmProtocol httpScmProtocol; + private final InitializingHttpScmProtocolWrapper protocolWrapper; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index 0dda4306c6..96d0dc82c7 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -45,7 +45,6 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; import sonia.scm.repository.SvnRepositoryHandler; -import sonia.scm.repository.spi.HttpScmProtocol; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; @@ -63,7 +62,7 @@ import java.io.IOException; * @author Sebastian Sdorra */ @Singleton -public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol +public class SvnDAVServlet extends DAVServlet { /** Field description */ @@ -285,7 +284,7 @@ public class SvnDAVServlet extends DAVServlet implements HttpScmProtocol private final RepositoryProvider repositoryProvider; } - @Override +// @Override public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { service(request, response); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index 62d7abedf7..5ca5d13219 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -67,6 +67,6 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Mon, 10 Sep 2018 14:48:22 +0200 Subject: [PATCH 15/48] Inject uri info for http protocol url computation --- .../main/java/sonia/scm/repository/api/ScmProtocol.java | 4 +--- .../java/sonia/scm/repository/spi/HttpScmProtocol.java | 9 ++++++--- .../spi/InitializingHttpScmProtocolWrapper.java | 7 +++++-- .../sonia/scm/repository/api/RepositoryServiceTest.java | 3 ++- .../sonia/scm/web/GitScmProtocolProviderWrapper.java | 5 +++-- .../java/sonia/scm/web/HgScmProtocolProviderWrapper.java | 5 +++-- .../sonia/scm/web/SvnScmProtocolProviderWrapper.java | 5 +++-- .../v2/resources/RepositoryToRepositoryDtoMapper.java | 2 +- .../java/sonia/scm/api/v2/resources/MockScmProtocol.java | 4 +--- 9 files changed, 25 insertions(+), 19 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java index b865d6e55b..c987510491 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocol.java @@ -1,7 +1,5 @@ package sonia.scm.repository.api; -import java.net.URI; - /** * An ScmProtocol represents a concrete protocol provided by the SCM-Manager instance * to interact with a repository depending on its type. There may be multiple protocols @@ -17,5 +15,5 @@ public interface ScmProtocol { /** * The URL to access the repository providing this protocol. */ - String getUrl(URI baseUri); + String getUrl(); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index 310b663d5d..f2d49b8570 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -7,15 +7,18 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.net.URI; public abstract class HttpScmProtocol implements ScmProtocol { private final Repository repository; + private final UriInfo uriInfo; - public HttpScmProtocol(Repository repository) { + public HttpScmProtocol(Repository repository, UriInfo uriInfo) { this.repository = repository; + this.uriInfo = uriInfo; } @Override @@ -24,8 +27,8 @@ public abstract class HttpScmProtocol implements ScmProtocol { } @Override - public String getUrl(URI baseUri) { - return baseUri.resolve(URI.create("repo" + "/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + public String getUrl() { + return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); } public abstract void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index b83386a380..e2634826b1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,5 +1,6 @@ package sonia.scm.repository.spi; +import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.Repository; import javax.inject.Provider; @@ -13,12 +14,14 @@ import java.io.IOException; public abstract class InitializingHttpScmProtocolWrapper { private final Provider delegateProvider; + private final Provider uriInfoStore; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider uriInfoStore) { this.delegateProvider = delegateProvider; + this.uriInfoStore = uriInfoStore; } protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { @@ -32,7 +35,7 @@ public abstract class InitializingHttpScmProtocolWrapper { private class ProtocolWrapper extends HttpScmProtocol { public ProtocolWrapper(Repository repository) { - super(repository); + super(repository, uriInfoStore.get().get()); } @Override diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index 0f7914b4b0..cc6d02e076 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -8,6 +8,7 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriInfo; import java.util.Collection; import java.util.Collections; @@ -45,7 +46,7 @@ public class RepositoryServiceTest { private static class DummyHttpProtocol extends HttpScmProtocol { public DummyHttpProtocol(Repository repository) { - super(repository); + super(repository, mock(UriInfo.class)); } @Override diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index 5cc7383500..f2210259c2 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -1,5 +1,6 @@ package sonia.scm.web; +import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -9,7 +10,7 @@ import javax.inject.Singleton; @Singleton public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public GitScmProtocolProviderWrapper(Provider servletProvider) { - super(servletProvider); + public GitScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { + super(servletProvider, uriInfoStore); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index c67c68024e..a69ff10512 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -1,5 +1,6 @@ package sonia.scm.web; +import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -9,7 +10,7 @@ import javax.inject.Singleton; @Singleton public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public HgScmProtocolProviderWrapper(Provider servletProvider) { - super(servletProvider); + public HgScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { + super(servletProvider, uriInfoStore); } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 5544bf796e..4e619e27f8 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -1,5 +1,6 @@ package sonia.scm.web; +import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -16,8 +17,8 @@ import static sonia.scm.web.SvnServletModule.PARAMETER_SVN_PARENTPATH; @Singleton public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public SvnScmProtocolProviderWrapper(Provider servletProvider) { - super(servletProvider); + public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { + super(servletProvider, uriInfoStore); } @Override diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index 5ca5d13219..74ce1a65dd 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -67,6 +67,6 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Mon, 10 Sep 2018 15:49:11 +0200 Subject: [PATCH 16/48] Correct user agent in git lfs test --- scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java index 2452afb909..b07f0c6067 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java @@ -52,6 +52,7 @@ import sonia.scm.repository.PermissionType; import sonia.scm.repository.Repository; import sonia.scm.user.User; import sonia.scm.user.UserTestData; +import sonia.scm.util.HttpUtil; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -221,7 +222,7 @@ public class GitLfsITCase { LfsResponseBody response = request(client, request); String uploadURL = response.objects[0].actions.upload.href; - client.resource(uploadURL).put(data); + client.resource(uploadURL).header(HttpUtil.HEADER_USERAGENT, "git-lfs/z").put(data); return lfsObject; } @@ -233,13 +234,14 @@ public class GitLfsITCase { String json = client .resource(batchUrl) .accept("application/vnd.git-lfs+json") + .header(HttpUtil.HEADER_USERAGENT, "git-lfs/z") .header("Content-Type", "application/vnd.git-lfs+json") .post(String.class, requestAsString); return new ObjectMapperProvider().get().readValue(json, LfsResponseBody.class); } private String createBatchUrl() { - String url = BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName(); + String url = BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName(); return url + "/info/lfs/objects/batch"; } @@ -248,7 +250,7 @@ public class GitLfsITCase { LfsResponseBody response = request(client, request); String downloadUrl = response.objects[0].actions.download.href; - return client.resource(downloadUrl).get(byte[].class); + return client.resource(downloadUrl).header(HttpUtil.HEADER_USERAGENT, "git-lfs/z").get(byte[].class); } private LfsObject createLfsObject(byte[] data) { From 5f667a2428d3a9a0e9141a9a34807ba8fe4c3961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 15:50:55 +0200 Subject: [PATCH 17/48] Correct url in git path mather test --- .../test/java/sonia/scm/it/GitRepositoryPathMatcherITCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitRepositoryPathMatcherITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitRepositoryPathMatcherITCase.java index 13cae15907..9e75857f08 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/GitRepositoryPathMatcherITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/GitRepositoryPathMatcherITCase.java @@ -100,7 +100,7 @@ public class GitRepositoryPathMatcherITCase { // tests end private String createUrl() { - return BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName(); + return BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName(); } private void cloneAndPush( String url ) throws IOException { From d9d3167bbb1416939c7d852ca10bde52099564c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 15:53:03 +0200 Subject: [PATCH 18/48] Correct url in repository hook test --- scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java b/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java index dae80cd00d..6ad8342d8a 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java @@ -196,7 +196,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase private RepositoryClient createRepositoryClient() throws IOException { return REPOSITORY_CLIENT_FACTORY.create(repositoryType, - IntegrationTestUtil.BASE_URL + repositoryType + "/" + repository.getNamespace() + "/" + repository.getName(), + IntegrationTestUtil.BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName(), IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy ); } From eb378de87f46e31f7b937996aaf6bca76c3bfca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 16:35:50 +0200 Subject: [PATCH 19/48] Use existing permission filters in http servlet protocol Just as a POC, fix logging and public access. --- .../scm/repository/spi/HttpScmProtocol.java | 4 ++ .../InitializingHttpScmProtocolWrapper.java | 41 ++++++++++++++++++- .../scm/web/filter/PermissionFilter.java | 6 +-- .../sonia/scm/web/GitPermissionFilter.java | 2 +- .../web/GitScmProtocolProviderWrapper.java | 4 +- .../sonia/scm/web/HgPermissionFilter.java | 2 +- .../scm/web/HgScmProtocolProviderWrapper.java | 4 +- .../sonia/scm/web/SvnPermissionFilter.java | 2 +- .../web/SvnScmProtocolProviderWrapper.java | 4 +- 9 files changed, 55 insertions(+), 14 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index f2d49b8570..51467d9f5c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -32,4 +32,8 @@ public abstract class HttpScmProtocol implements ScmProtocol { } public abstract void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; + + Repository getRepository() { + return repository; + } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index e2634826b1..ba63cf8501 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,7 +1,13 @@ package sonia.scm.repository.spi; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.Repository; +import sonia.scm.web.filter.PermissionFilter; +import sonia.scm.web.filter.ProviderPermissionFilter; import javax.inject.Provider; import javax.servlet.ServletConfig; @@ -13,14 +19,19 @@ import java.io.IOException; public abstract class InitializingHttpScmProtocolWrapper { + private static final Logger logger = + LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); + private final Provider delegateProvider; + private final Provider permissionFilterProvider; private final Provider uriInfoStore; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider uriInfoStore) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { this.delegateProvider = delegateProvider; + this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; } @@ -49,7 +60,33 @@ public abstract class InitializingHttpScmProtocolWrapper { } } } - delegateProvider.get().service(request, response); + + if (getRepository() != null) + { + Subject subject = SecurityUtils.getSubject(); + + PermissionFilter permissionFilter = permissionFilterProvider.get(); + boolean writeRequest = permissionFilter.isWriteRequest(request); + + if (permissionFilter.hasPermission(getRepository(), writeRequest)) + { +// logger.trace("{} access to repository {} for user {} granted", +// getActionAsString(writeRequest), repository.getName(), +// getUserName(subject)); + + delegateProvider.get().service(request, response); + } + else + { +// logger.info("{} access to repository {} for user {} denied", +// getActionAsString(writeRequest), repository.getName(), +// getUserName(subject)); + + permissionFilter.sendAccessDenied(request, response, subject); + } + } + } } + } diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index dd3c82e800..732bac1c57 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -106,7 +106,7 @@ public abstract class PermissionFilter extends HttpFilter * * @return returns true if the current request is a write request */ - protected abstract boolean isWriteRequest(HttpServletRequest request); + public abstract boolean isWriteRequest(HttpServletRequest request); //~--- methods -------------------------------------------------------------- @@ -249,7 +249,7 @@ public abstract class PermissionFilter extends HttpFilter * * @throws IOException */ - private void sendAccessDenied(HttpServletRequest request, + public void sendAccessDenied(HttpServletRequest request, HttpServletResponse response, Subject subject) throws IOException { @@ -328,7 +328,7 @@ public abstract class PermissionFilter extends HttpFilter * * @return true if the current user has the required permissions */ - private boolean hasPermission(Repository repository, boolean writeRequest) + public boolean hasPermission(Repository repository, boolean writeRequest) { boolean permitted; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index 068284188d..ca88e06a41 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -98,7 +98,7 @@ public class GitPermissionFilter extends ProviderPermissionFilter } @Override - protected boolean isWriteRequest(HttpServletRequest request) { + public boolean isWriteRequest(HttpServletRequest request) { return isReceivePackRequest(request) || isReceiveServiceRequest(request) || isLfsFileUpload(request); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index f2210259c2..ae378c2439 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -10,7 +10,7 @@ import javax.inject.Singleton; @Singleton public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public GitScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { - super(servletProvider, uriInfoStore); + public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { + super(servletProvider, permissionFilter, uriInfoStore); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index c05f03dc4e..9350f8399c 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -74,7 +74,7 @@ public class HgPermissionFilter extends ProviderPermissionFilter //~--- get methods ---------------------------------------------------------- @Override - protected boolean isWriteRequest(HttpServletRequest request) + public boolean isWriteRequest(HttpServletRequest request) { return !READ_METHODS.contains(request.getMethod()); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index a69ff10512..ba5c40e7f9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -10,7 +10,7 @@ import javax.inject.Singleton; @Singleton public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public HgScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { - super(servletProvider, uriInfoStore); + public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { + super(servletProvider, permissionFilter, uriInfoStore); } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 857e3d6d71..43a4f1baec 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -126,7 +126,7 @@ public class SvnPermissionFilter extends ProviderPermissionFilter * @return */ @Override - protected boolean isWriteRequest(HttpServletRequest request) + public boolean isWriteRequest(HttpServletRequest request) { return WRITEMETHOD_SET.contains(request.getMethod().toUpperCase()); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 4e619e27f8..7907e55dcc 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -17,8 +17,8 @@ import static sonia.scm.web.SvnServletModule.PARAMETER_SVN_PARENTPATH; @Singleton public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider uriInfoStore) { - super(servletProvider, uriInfoStore); + public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { + super(servletProvider, permissionFilter, uriInfoStore); } @Override From 1b200ae69dfa6e07078c363430f43ded7e79ed20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Sep 2018 16:58:52 +0200 Subject: [PATCH 20/48] Remove http request filter implementation from permission filters --- .../InitializingHttpScmProtocolWrapper.java | 34 ++-------- .../scm/web/filter/PermissionFilter.java | 63 +++++++------------ .../web/filter/ProviderPermissionFilter.java | 49 +-------------- .../sonia/scm/web/GitPermissionFilter.java | 6 +- .../scm/web/GitPermissionFilterTest.java | 8 +-- .../sonia/scm/web/HgPermissionFilter.java | 7 +-- .../sonia/scm/web/SvnPermissionFilter.java | 7 +-- 7 files changed, 35 insertions(+), 139 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index ba63cf8501..12a62d13c5 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,12 +1,9 @@ package sonia.scm.repository.spi; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.Repository; -import sonia.scm.web.filter.PermissionFilter; import sonia.scm.web.filter.ProviderPermissionFilter; import javax.inject.Provider; @@ -61,32 +58,11 @@ public abstract class InitializingHttpScmProtocolWrapper { } } - if (getRepository() != null) - { - Subject subject = SecurityUtils.getSubject(); - - PermissionFilter permissionFilter = permissionFilterProvider.get(); - boolean writeRequest = permissionFilter.isWriteRequest(request); - - if (permissionFilter.hasPermission(getRepository(), writeRequest)) - { -// logger.trace("{} access to repository {} for user {} granted", -// getActionAsString(writeRequest), repository.getName(), -// getUserName(subject)); - - delegateProvider.get().service(request, response); - } - else - { -// logger.info("{} access to repository {} for user {} denied", -// getActionAsString(writeRequest), repository.getName(), -// getUserName(subject)); - - permissionFilter.sendAccessDenied(request, response, subject); - } - } - + permissionFilterProvider.get().executeIfPermitted( + request, + response, + getRepository(), + () -> delegateProvider.get().service(request, response)); } } - } diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index 732bac1c57..8831756234 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -51,7 +51,6 @@ import sonia.scm.security.ScmSecurityException; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; -import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -65,7 +64,7 @@ import java.util.Iterator; * * @author Sebastian Sdorra */ -public abstract class PermissionFilter extends HttpFilter +public abstract class PermissionFilter { /** the logger for PermissionFilter */ @@ -81,23 +80,13 @@ public abstract class PermissionFilter extends HttpFilter * * @since 1.21 */ - public PermissionFilter(ScmConfiguration configuration) + protected PermissionFilter(ScmConfiguration configuration) { this.configuration = configuration; } //~--- get methods ---------------------------------------------------------- - /** - * Returns the requested repository. - * - * - * @param request current http request - * - * @return requested repository - */ - protected abstract Repository getRepository(HttpServletRequest request); - /** * Returns true if the current request is a write request. * @@ -106,7 +95,7 @@ public abstract class PermissionFilter extends HttpFilter * * @return returns true if the current request is a write request */ - public abstract boolean isWriteRequest(HttpServletRequest request); + protected abstract boolean isWriteRequest(HttpServletRequest request); //~--- methods -------------------------------------------------------------- @@ -117,48 +106,35 @@ public abstract class PermissionFilter extends HttpFilter * * @param request http request * @param response http response - * @param chain filter chain * * @throws IOException * @throws ServletException */ - @Override - protected void doFilter(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) + public void executeIfPermitted(HttpServletRequest request, + HttpServletResponse response, Repository repository, ContinuationServlet continuation) throws IOException, ServletException { Subject subject = SecurityUtils.getSubject(); try { - Repository repository = getRepository(request); + boolean writeRequest = isWriteRequest(request); - if (repository != null) + if (hasPermission(repository, writeRequest)) { - boolean writeRequest = isWriteRequest(request); + logger.trace("{} access to repository {} for user {} granted", + getActionAsString(writeRequest), repository.getName(), + getUserName(subject)); - if (hasPermission(repository, writeRequest)) - { - logger.trace("{} access to repository {} for user {} granted", - getActionAsString(writeRequest), repository.getName(), - getUserName(subject)); - - chain.doFilter(request, response); - } - else - { - logger.info("{} access to repository {} for user {} denied", - getActionAsString(writeRequest), repository.getName(), - getUserName(subject)); - - sendAccessDenied(request, response, subject); - } + continuation.serve(); } else { - logger.debug("repository not found"); + logger.info("{} access to repository {} for user {} denied", + getActionAsString(writeRequest), repository.getName(), + getUserName(subject)); - response.sendError(HttpServletResponse.SC_NOT_FOUND); + sendAccessDenied(request, response, subject); } } catch (ArgumentIsInvalidException ex) @@ -249,7 +225,7 @@ public abstract class PermissionFilter extends HttpFilter * * @throws IOException */ - public void sendAccessDenied(HttpServletRequest request, + private void sendAccessDenied(HttpServletRequest request, HttpServletResponse response, Subject subject) throws IOException { @@ -328,7 +304,7 @@ public abstract class PermissionFilter extends HttpFilter * * @return true if the current user has the required permissions */ - public boolean hasPermission(Repository repository, boolean writeRequest) + private boolean hasPermission(Repository repository, boolean writeRequest) { boolean permitted; @@ -348,4 +324,9 @@ public abstract class PermissionFilter extends HttpFilter /** scm-manager global configuration */ private final ScmConfiguration configuration; + + @FunctionalInterface + public interface ContinuationServlet { + void serve() throws ServletException, IOException; + } } diff --git a/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java index ea0d90c915..280ea0a77b 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java @@ -35,22 +35,12 @@ package sonia.scm.web.filter; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.base.Throwables; -import com.google.inject.ProvisionException; - -import org.apache.shiro.authz.AuthorizationException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.Repository; -import sonia.scm.repository.RepositoryProvider; //~--- JDK imports ------------------------------------------------------------ -import javax.servlet.http.HttpServletRequest; - /** * * @author Sebastian Sdorra @@ -72,47 +62,10 @@ public abstract class ProviderPermissionFilter extends PermissionFilter * * * @param configuration - * @param repositoryProvider * @since 1.21 */ - public ProviderPermissionFilter(ScmConfiguration configuration, - RepositoryProvider repositoryProvider) + public ProviderPermissionFilter(ScmConfiguration configuration) { super(configuration); - this.repositoryProvider = repositoryProvider; } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param request - * - * @return - */ - @Override - protected Repository getRepository(HttpServletRequest request) - { - Repository repository = null; - - try - { - repository = repositoryProvider.get(); - } - catch (ProvisionException ex) - { - Throwables.propagateIfPossible(ex.getCause(), - IllegalStateException.class, AuthorizationException.class); - logger.error("could not get repository from request", ex); - } - - return repository; - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private final RepositoryProvider repositoryProvider; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index ca88e06a41..5606b73762 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -43,7 +43,6 @@ import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; import sonia.scm.filter.Filters; import sonia.scm.repository.GitUtil; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.web.filter.ProviderPermissionFilter; import javax.servlet.http.HttpServletRequest; @@ -78,11 +77,10 @@ public class GitPermissionFilter extends ProviderPermissionFilter * Constructs a new instance of the GitPermissionFilter. * * @param configuration scm main configuration - * @param repositoryProvider repository provider */ @Inject - public GitPermissionFilter(ScmConfiguration configuration, RepositoryProvider repositoryProvider) { - super(configuration, repositoryProvider); + public GitPermissionFilter(ScmConfiguration configuration) { + super(configuration); } @Override diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java index fede8842a9..8e7ff3d954 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java @@ -5,7 +5,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.util.HttpUtil; import javax.servlet.ServletOutputStream; @@ -29,12 +28,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class GitPermissionFilterTest { - @Mock - private RepositoryProvider repositoryProvider; - - private final GitPermissionFilter permissionFilter = new GitPermissionFilter( - new ScmConfiguration(), repositoryProvider - ); + private final GitPermissionFilter permissionFilter = new GitPermissionFilter(new ScmConfiguration()); @Mock private HttpServletResponse response; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index 9350f8399c..3a1aba93e4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -38,7 +38,6 @@ package sonia.scm.web; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.web.filter.ProviderPermissionFilter; import javax.servlet.http.HttpServletRequest; @@ -62,13 +61,11 @@ public class HgPermissionFilter extends ProviderPermissionFilter * Constructs a new instance. * * @param configuration scm configuration - * @param repositoryProvider repository provider */ @Inject - public HgPermissionFilter(ScmConfiguration configuration, - RepositoryProvider repositoryProvider) + public HgPermissionFilter(ScmConfiguration configuration) { - super(configuration, repositoryProvider); + super(configuration); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 43a4f1baec..2939b44753 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -39,7 +39,6 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.ScmSvnErrorCode; import sonia.scm.repository.SvnUtil; import sonia.scm.web.filter.ProviderPermissionFilter; @@ -71,13 +70,11 @@ public class SvnPermissionFilter extends ProviderPermissionFilter * Constructs ... * * @param configuration - * @param repository */ @Inject - public SvnPermissionFilter(ScmConfiguration configuration, - RepositoryProvider repository) + public SvnPermissionFilter(ScmConfiguration configuration) { - super(configuration, repository); + super(configuration); } //~--- methods -------------------------------------------------------------- From bf9de8ea8ed105776270cc0d9fbb82912d231404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 07:40:24 +0200 Subject: [PATCH 21/48] Reduce dependency to RepositoryProvider in provider servlets --- .../scm/repository/spi/HttpScmProtocol.java | 8 +-- .../InitializingHttpScmProtocolWrapper.java | 15 +++--- .../spi/ScmProviderHttpServlet.java | 16 ++++++ .../repository/api/RepositoryServiceTest.java | 2 +- .../java/sonia/scm/web/ScmGitServlet.java | 47 ++--------------- .../main/java/sonia/scm/web/HgCGIServlet.java | 44 +++------------- .../java/sonia/scm/web/SvnDAVServlet.java | 51 +++++-------------- .../web/SvnScmProtocolProviderWrapper.java | 4 +- 8 files changed, 52 insertions(+), 135 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServlet.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index 51467d9f5c..b93deba10a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -31,9 +31,9 @@ public abstract class HttpScmProtocol implements ScmProtocol { return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); } - public abstract void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException; - - Repository getRepository() { - return repository; + public final void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { + serve(request, response, repository, config); } + + protected abstract void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) throws ServletException, IOException; } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 12a62d13c5..22f7a25b57 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -9,7 +9,6 @@ import sonia.scm.web.filter.ProviderPermissionFilter; import javax.inject.Provider; import javax.servlet.ServletConfig; import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -19,20 +18,20 @@ public abstract class InitializingHttpScmProtocolWrapper { private static final Logger logger = LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); - private final Provider delegateProvider; + private final Provider delegateProvider; private final Provider permissionFilterProvider; private final Provider uriInfoStore; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { this.delegateProvider = delegateProvider; this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; } - protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { + protected void initializeServlet(ServletConfig config, ScmProviderHttpServlet httpServlet) throws ServletException { httpServlet.init(config); } @@ -47,11 +46,11 @@ public abstract class InitializingHttpScmProtocolWrapper { } @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { + protected void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) throws ServletException, IOException { if (!isInitialized) { synchronized (InitializingHttpScmProtocolWrapper.this) { if (!isInitialized) { - HttpServlet httpServlet = delegateProvider.get(); + ScmProviderHttpServlet httpServlet = delegateProvider.get(); initializeServlet(config, httpServlet); isInitialized = true; } @@ -61,8 +60,8 @@ public abstract class InitializingHttpScmProtocolWrapper { permissionFilterProvider.get().executeIfPermitted( request, response, - getRepository(), - () -> delegateProvider.get().service(request, response)); + repository, + () -> delegateProvider.get().service(request, response, repository)); } } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServlet.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServlet.java new file mode 100644 index 0000000000..3a9dad52d6 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServlet.java @@ -0,0 +1,16 @@ +package sonia.scm.repository.spi; + +import sonia.scm.repository.Repository; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public interface ScmProviderHttpServlet { + + void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException; + + void init(ServletConfig config) throws ServletException; +} diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index cc6d02e076..1783d17936 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -50,7 +50,7 @@ public class RepositoryServiceTest { } @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { + public void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) { } } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java index 261e67c185..8ec81d43f3 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java @@ -42,8 +42,8 @@ import org.eclipse.jgit.http.server.GitServlet; import org.eclipse.jgit.lfs.lib.Constants; import org.slf4j.Logger; import sonia.scm.repository.Repository; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.util.HttpUtil; import sonia.scm.web.lfs.servlet.LfsServletFactory; @@ -64,7 +64,7 @@ import static org.slf4j.LoggerFactory.getLogger; * @author Sebastian Sdorra */ @Singleton -public class ScmGitServlet extends GitServlet +public class ScmGitServlet extends GitServlet implements ScmProviderHttpServlet { /** Field description */ @@ -88,7 +88,6 @@ public class ScmGitServlet extends GitServlet * @param repositoryResolver * @param receivePackFactory * @param repositoryViewer - * @param repositoryProvider * @param repositoryRequestListenerUtil * @param lfsServletFactory */ @@ -96,11 +95,9 @@ public class ScmGitServlet extends GitServlet public ScmGitServlet(GitRepositoryResolver repositoryResolver, GitReceivePackFactory receivePackFactory, GitRepositoryViewer repositoryViewer, - RepositoryProvider repositoryProvider, RepositoryRequestListenerUtil repositoryRequestListenerUtil, LfsServletFactory lfsServletFactory) { - this.repositoryProvider = repositoryProvider; this.repositoryViewer = repositoryViewer; this.repositoryRequestListenerUtil = repositoryRequestListenerUtil; this.lfsServletFactory = lfsServletFactory; @@ -122,44 +119,9 @@ public class ScmGitServlet extends GitServlet * @throws ServletException */ @Override - protected void service(HttpServletRequest request, - HttpServletResponse response) + public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { - Repository repository = repositoryProvider.get(); - if (repository != null) { - handleRequest(request, response, repository); - } else { - // logger - response.sendError(HttpServletResponse.SC_NOT_FOUND); - } - } - - /** - * Decides the type request being currently made and delegates it accordingly. - *
    - *
  • Batch API:
  • - *
      - *
    • used to provide the client with information on how handle the large files of a repository.
    • - *
    • response contains the information where to perform the actual upload and download of the large objects.
    • - *
    - *
  • Transfer API:
  • - *
      - *
    • receives and provides the actual large objects (resolves the pointer placed in the file of the working copy).
    • - *
    • invoked only after the Batch API has been questioned about what to do with the large files
    • - *
    - *
  • Regular Git Http API:
  • - *
      - *
    • regular git http wire protocol, use by normal git clients.
    • - *
    - *
  • Browser Overview:
  • - *
      - *
    • short repository overview for browser clients.
    • - *
    - *
  • - *
- */ - private void handleRequest(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { String repoPath = repository.getNamespace() + "/" + repository.getName(); logger.trace("handle git repository at {}", repoPath); if (isLfsBatchApiRequest(request, repoPath)) { @@ -286,9 +248,6 @@ public class ScmGitServlet extends GitServlet //~--- fields --------------------------------------------------------------- - /** Field description */ - private final RepositoryProvider repositoryProvider; - /** Field description */ private final RepositoryRequestListenerUtil repositoryRequestListenerUtil; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index f8fabbc040..f3e6a54568 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -49,8 +49,8 @@ import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgPythonScript; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; -import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.security.CipherUtil; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; @@ -58,7 +58,6 @@ import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.EnvList; -import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -76,7 +75,7 @@ import java.util.Enumeration; * @author Sebastian Sdorra */ @Singleton -public class HgCGIServlet extends HttpServlet +public class HgCGIServlet extends HttpServlet implements ScmProviderHttpServlet { /** Field description */ @@ -109,20 +108,18 @@ public class HgCGIServlet extends HttpServlet * * @param cgiExecutorFactory * @param configuration - * @param repositoryProvider * @param handler * @param hookManager * @param requestListenerUtil */ @Inject public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory, - ScmConfiguration configuration, RepositoryProvider repositoryProvider, + ScmConfiguration configuration, HgRepositoryHandler handler, HgHookManager hookManager, RepositoryRequestListenerUtil requestListenerUtil) { this.cgiExecutorFactory = cgiExecutorFactory; this.configuration = configuration; - this.repositoryProvider = repositoryProvider; this.handler = handler; this.hookManager = hookManager; this.requestListenerUtil = requestListenerUtil; @@ -132,32 +129,11 @@ public class HgCGIServlet extends HttpServlet //~--- methods -------------------------------------------------------------- - /** - * Method description - * - * - * @param request - * @param response - * - * @throws IOException - * @throws ServletException - */ @Override - protected void service(HttpServletRequest request, - HttpServletResponse response) + public void service(HttpServletRequest request, + HttpServletResponse response, Repository repository) { - Repository repository = repositoryProvider.get(); - - if (repository == null) - { - if (logger.isDebugEnabled()) - { - logger.debug("no hg repository found at {}", request.getRequestURI()); - } - - response.setStatus(HttpServletResponse.SC_NOT_FOUND); - } - else if (!handler.isConfigured()) + if (!handler.isConfigured()) { exceptionHandler.sendFormattedError(request, response, HgCGIExceptionHandler.ERROR_NOT_CONFIGURED); @@ -346,11 +322,6 @@ public class HgCGIServlet extends HttpServlet return python; } -// @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) { - service(request, response); - } - //~--- fields --------------------------------------------------------------- /** Field description */ @@ -371,9 +342,6 @@ public class HgCGIServlet extends HttpServlet /** Field description */ private final HgHookManager hookManager; - /** Field description */ - private final RepositoryProvider repositoryProvider; - /** Field description */ private final RepositoryRequestListenerUtil requestListenerUtil; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index 96d0dc82c7..35b420257d 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -45,10 +45,10 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; -import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; @@ -62,7 +62,7 @@ import java.io.IOException; * @author Sebastian Sdorra */ @Singleton -public class SvnDAVServlet extends DAVServlet +public class SvnDAVServlet extends DAVServlet implements ScmProviderHttpServlet { /** Field description */ @@ -111,28 +111,18 @@ public class SvnDAVServlet extends DAVServlet * @throws ServletException */ @Override - public void service(HttpServletRequest request, HttpServletResponse response) + public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { - Repository repository = repositoryProvider.get(); - - if (repository != null) - { - if (repositoryRequestListenerUtil.callListeners(request, response, - repository)) - { - super.service(new SvnHttpServletRequestWrapper(request, - repositoryProvider), response); - } - else if (logger.isDebugEnabled()) - { - logger.debug("request aborted by repository request listener"); - } - } - else + if (repositoryRequestListenerUtil.callListeners(request, response, + repository)) { super.service(new SvnHttpServletRequestWrapper(request, - repositoryProvider), response); + repository), response); + } + else if (logger.isDebugEnabled()) + { + logger.debug("request aborted by repository request listener"); } } @@ -164,18 +154,11 @@ public class SvnDAVServlet extends DAVServlet extends HttpServletRequestWrapper { - /** - * Constructs ... - * - * - * @param request - * @param repositoryProvider - */ public SvnHttpServletRequestWrapper(HttpServletRequest request, - RepositoryProvider repositoryProvider) + Repository repository) { super(request); - this.repositoryProvider = repositoryProvider; + this.repository = repository; } //~--- get methods -------------------------------------------------------- @@ -212,8 +195,6 @@ public class SvnDAVServlet extends DAVServlet AssertUtil.assertIsNotEmpty(pathInfo); - Repository repository = repositoryProvider.get(); - if (repository != null) { if (pathInfo.startsWith(HttpUtil.SEPARATOR_PATH)) @@ -237,7 +218,6 @@ public class SvnDAVServlet extends DAVServlet public String getServletPath() { String servletPath = super.getServletPath(); - Repository repository = repositoryProvider.get(); if (repository != null) { @@ -281,12 +261,7 @@ public class SvnDAVServlet extends DAVServlet //~--- fields ------------------------------------------------------------- /** Field description */ - private final RepositoryProvider repositoryProvider; - } - -// @Override - public void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { - service(request, response); + private final Repository repository; } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 7907e55dcc..90ac29aa12 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import javax.inject.Inject; import javax.inject.Provider; @@ -9,7 +10,6 @@ import javax.inject.Singleton; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; import java.util.Enumeration; import static sonia.scm.web.SvnServletModule.PARAMETER_SVN_PARENTPATH; @@ -22,7 +22,7 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr } @Override - protected void initializeServlet(ServletConfig config, HttpServlet httpServlet) throws ServletException { + protected void initializeServlet(ServletConfig config, ScmProviderHttpServlet httpServlet) throws ServletException { super.initializeServlet(new X(config), httpServlet); } From e90dc11bc7f3c4e762a0579d5eeaebc5d7fec347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 10:50:53 +0200 Subject: [PATCH 22/48] Cleanup for http protocol servlet changes --- .../sonia/scm/ArgumentIsInvalidException.java | 85 --------------- .../InitializingHttpScmProtocolWrapper.java | 6 +- .../spi/RepositoryServiceProvider.java | 4 - .../scm/web/filter/PermissionFilter.java | 40 ------- .../web/filter/ProviderPermissionFilter.java | 71 ------------ .../spi/GitRepositoryServiceProvider.java | 4 - .../spi/GitRepositoryServiceResolver.java | 28 +---- .../sonia/scm/web/GitPermissionFilter.java | 12 +-- .../java/sonia/scm/web/GitServletModule.java | 12 --- .../java/sonia/scm/web/ScmGitServlet.java | 13 +-- .../spi/HgRepositoryServiceProvider.java | 4 - .../spi/HgRepositoryServiceResolver.java | 2 - .../scm/web/HgBasicAuthenticationFilter.java | 102 ------------------ .../main/java/sonia/scm/web/HgCGIServlet.java | 4 - .../sonia/scm/web/HgPermissionFilter.java | 17 +-- .../spi/SvnRepositoryServiceProvider.java | 4 - .../spi/SvnRepositoryServiceResolver.java | 41 +------ .../scm/web/SvnBasicAuthenticationFilter.java | 96 ----------------- .../java/sonia/scm/web/SvnDAVServlet.java | 4 - .../sonia/scm/web/SvnPermissionFilter.java | 10 +- .../web/SvnScmProtocolProviderWrapper.java | 11 +- .../java/sonia/scm/web/SvnServletModule.java | 26 +---- .../java/sonia/scm/ScmContextListener.java | 4 - .../main/java/sonia/scm/ScmServletModule.java | 12 --- .../resources/RepositoryRootResource.java | 4 - .../repository/DefaultRepositoryManager.java | 4 - .../repository/DefaultRepositoryProvider.java | 8 +- 27 files changed, 32 insertions(+), 596 deletions(-) delete mode 100644 scm-core/src/main/java/sonia/scm/ArgumentIsInvalidException.java delete mode 100644 scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java delete mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java delete mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java diff --git a/scm-core/src/main/java/sonia/scm/ArgumentIsInvalidException.java b/scm-core/src/main/java/sonia/scm/ArgumentIsInvalidException.java deleted file mode 100644 index 727e9a8160..0000000000 --- a/scm-core/src/main/java/sonia/scm/ArgumentIsInvalidException.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - -package sonia.scm; - -/** - * - * @author Sebastian Sdorra - * @since 1.17 - */ -public class ArgumentIsInvalidException extends IllegalStateException -{ - - /** - * Constructs ... - * - */ - public ArgumentIsInvalidException() - { - super(); - } - - /** - * Constructs ... - * - * - * @param s - */ - public ArgumentIsInvalidException(String s) - { - super(s); - } - - /** - * Constructs ... - * - * - * @param cause - */ - public ArgumentIsInvalidException(Throwable cause) - { - super(cause); - } - - /** - * Constructs ... - * - * - * @param message - * @param cause - */ - public ArgumentIsInvalidException(String message, Throwable cause) - { - super(message, cause); - } -} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 22f7a25b57..3d4d3c6205 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.repository.Repository; -import sonia.scm.web.filter.ProviderPermissionFilter; +import sonia.scm.web.filter.PermissionFilter; import javax.inject.Provider; import javax.servlet.ServletConfig; @@ -19,13 +19,13 @@ public abstract class InitializingHttpScmProtocolWrapper { LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); private final Provider delegateProvider; - private final Provider permissionFilterProvider; + private final Provider permissionFilterProvider; private final Provider uriInfoStore; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { this.delegateProvider = delegateProvider; this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java index d44db74f7c..0a56800f82 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java @@ -33,8 +33,6 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import sonia.scm.repository.Feature; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.CommandNotSupportedException; @@ -45,8 +43,6 @@ import java.io.IOException; import java.util.Collections; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index 8831756234..3415c3e338 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -33,15 +33,12 @@ package sonia.scm.web.filter; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.base.Splitter; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sonia.scm.ArgumentIsInvalidException; import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; @@ -57,8 +54,6 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Iterator; -//~--- JDK imports ------------------------------------------------------------ - /** * Abstract http filter to check repository permissions. * @@ -137,22 +132,6 @@ public abstract class PermissionFilter sendAccessDenied(request, response, subject); } } - catch (ArgumentIsInvalidException ex) - { - if (logger.isTraceEnabled()) - { - logger.trace( - "wrong request at ".concat(request.getRequestURI()).concat( - " send redirect"), ex); - } - else if (logger.isWarnEnabled()) - { - logger.warn("wrong request at {} send redirect", - request.getRequestURI()); - } - - response.sendRedirect(getRepositoryRootHelpUrl(request)); - } catch (ScmSecurityException | AuthorizationException ex) { logger.warn("user " + subject.getPrincipal() + " has not enough permissions", ex); @@ -256,25 +235,6 @@ public abstract class PermissionFilter : "read"; } - /** - * Returns the repository root help url. - * - * - * @param request current http request - * - * @return repository root help url - */ - private String getRepositoryRootHelpUrl(HttpServletRequest request) - { - String type = extractType(request); - String helpUrl = HttpUtil.getCompleteUrl(request, - "/api/rest/help/repository-root/"); - - helpUrl = helpUrl.concat(type).concat(".html"); - - return helpUrl; - } - /** * Returns the username from the given subject or anonymous. * diff --git a/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java deleted file mode 100644 index 280ea0a77b..0000000000 --- a/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - - -package sonia.scm.web.filter; - -//~--- non-JDK imports -------------------------------------------------------- - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sonia.scm.config.ScmConfiguration; - -//~--- JDK imports ------------------------------------------------------------ - -/** - * - * @author Sebastian Sdorra - * @since 1.9 - */ -public abstract class ProviderPermissionFilter extends PermissionFilter -{ - - /** - * the logger for ProviderPermissionFilter - */ - private static final Logger logger = - LoggerFactory.getLogger(ProviderPermissionFilter.class); - - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - * - * @param configuration - * @since 1.21 - */ - public ProviderPermissionFilter(ScmConfiguration configuration) - { - super(configuration); - } -} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 4874247785..235136938a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -33,8 +33,6 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.collect.ImmutableSet; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; @@ -45,8 +43,6 @@ import java.io.IOException; import java.util.Collections; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index 654b586088..d20eedca9f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -45,47 +45,27 @@ import sonia.scm.web.GitScmProtocolProviderWrapper; * @author Sebastian Sdorra */ @Extension -public class GitRepositoryServiceResolver implements RepositoryServiceResolver -{ +public class GitRepositoryServiceResolver implements RepositoryServiceResolver { - /** Field description */ public static final String TYPE = "git"; - //~--- constructors --------------------------------------------------------- - @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper providerWrapper) - { + public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper providerWrapper) { this.handler = handler; this.providerWrapper = providerWrapper; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param repository - * - * @return - */ @Override - public GitRepositoryServiceProvider resolve(Repository repository) - { + public GitRepositoryServiceProvider resolve(Repository repository) { GitRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) - { + if (TYPE.equalsIgnoreCase(repository.getType())) { provider = new GitRepositoryServiceProvider(handler, repository, providerWrapper.get(repository)); } return provider; } - //~--- fields --------------------------------------------------------------- - - /** Field description */ private final GitRepositoryHandler handler; private final GitScmProtocolProviderWrapper providerWrapper; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index 5606b73762..e183555b3b 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -33,32 +33,24 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import org.eclipse.jgit.http.server.GitSmartHttpTools; import sonia.scm.ClientMessages; -import sonia.scm.Priority; import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; import sonia.scm.repository.GitUtil; -import sonia.scm.web.filter.ProviderPermissionFilter; +import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -//~--- JDK imports ------------------------------------------------------------ - /** * GitPermissionFilter decides if a git request requires write or read privileges. * * @author Sebastian Sdorra */ -@Priority(Filters.PRIORITY_AUTHORIZATION) -//@WebElement(value = GitServletModule.PATTERN_GIT) -public class GitPermissionFilter extends ProviderPermissionFilter +public class GitPermissionFilter extends PermissionFilter { private static final String PARAMETER_SERVICE = "service"; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index 9b8d53caf2..e731e01a62 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -51,18 +51,6 @@ import sonia.scm.web.lfs.LfsBlobStoreFactory; public class GitServletModule extends ServletModule { - public static final String GIT_PATH = "/repo"; - - /** Field description */ - public static final String PATTERN_GIT = GIT_PATH + "/*"; - - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - */ @Override protected void configureServlets() { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java index 8ec81d43f3..2701764607 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java @@ -33,8 +33,6 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -57,8 +55,6 @@ import java.util.regex.Pattern; import static org.eclipse.jgit.lfs.lib.Constants.CONTENT_TYPE_GIT_LFS_JSON; import static org.slf4j.LoggerFactory.getLogger; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra @@ -67,7 +63,8 @@ import static org.slf4j.LoggerFactory.getLogger; public class ScmGitServlet extends GitServlet implements ScmProviderHttpServlet { - /** Field description */ + public static final String REPO_PATH = "/repo"; + public static final Pattern REGEX_GITHTTPBACKEND = Pattern.compile( "(?x)^/repo/(.*/(HEAD|info/refs|objects/(info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\\.(pack|idx))|git-(upload|receive)-pack))$" ); @@ -172,7 +169,7 @@ public class ScmGitServlet extends GitServlet implements ScmProviderHttpServlet * @throws IOException * @throws ServletException */ - private void handleBrowserRequest(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { + private void handleBrowserRequest(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException { try { repositoryViewer.handleRequest(request, response, repository); } catch (IOException ex) { @@ -191,7 +188,7 @@ public class ScmGitServlet extends GitServlet implements ScmProviderHttpServlet */ private static boolean isLfsFileTransferRequest(HttpServletRequest request, String repository) { - String regex = String.format("^%s%s/%s(\\.git)?/info/lfs/objects/[a-z0-9]{64}$", request.getContextPath(), GitServletModule.GIT_PATH, repository); + String regex = String.format("^%s%s/%s(\\.git)?/info/lfs/objects/[a-z0-9]{64}$", request.getContextPath(), REPO_PATH, repository); boolean pathMatches = request.getRequestURI().matches(regex); boolean methodMatches = request.getMethod().equals("PUT") || request.getMethod().equals("GET"); @@ -210,7 +207,7 @@ public class ScmGitServlet extends GitServlet implements ScmProviderHttpServlet */ private static boolean isLfsBatchApiRequest(HttpServletRequest request, String repository) { - String regex = String.format("^%s%s/%s(\\.git)?/info/lfs/objects/batch$", request.getContextPath(), GitServletModule.GIT_PATH, repository); + String regex = String.format("^%s%s/%s(\\.git)?/info/lfs/objects/batch$", request.getContextPath(), REPO_PATH, repository); boolean pathMatches = request.getRequestURI().matches(regex); boolean methodMatches = "POST".equals(request.getMethod()); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 1fc837029c..8c280a9915 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -33,8 +33,6 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.io.Closeables; import sonia.scm.repository.Feature; import sonia.scm.repository.HgHookManager; @@ -49,8 +47,6 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index 08db6d1dbd..c1accbad1a 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -33,8 +33,6 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.inject.Inject; import sonia.scm.plugin.Extension; import sonia.scm.repository.HgHookManager; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java deleted file mode 100644 index abc295fd68..0000000000 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. 2. Redistributions in - * binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. 3. Neither the name of SCM-Manager; - * nor the names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - - -package sonia.scm.web; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.inject.Inject; - -import sonia.scm.Priority; -import sonia.scm.config.ScmConfiguration; -import sonia.scm.filter.Filters; -import sonia.scm.filter.WebElement; -import sonia.scm.web.filter.AuthenticationFilter; - -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * - * @author Sebastian Sdorra - */ -@Priority(Filters.PRIORITY_AUTHENTICATION) -@WebElement(value = HgServletModule.MAPPING_HG) -public class HgBasicAuthenticationFilter extends AuthenticationFilter -{ - - /** - * Constructs ... - * - * - * @param configuration - * @param webTokenGenerators - */ - @Inject - public HgBasicAuthenticationFilter(ScmConfiguration configuration, - Set webTokenGenerators) - { - super(configuration, webTokenGenerators); - } - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param request - * @param response - * - * @throws IOException - */ - @Override - protected void sendFailedAuthenticationError(HttpServletRequest request, - HttpServletResponse response) - throws IOException - { - if (HgUtil.isHgClient(request) - && (configuration.isLoginAttemptLimitEnabled())) - { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - } - else - { - super.sendFailedAuthenticationError(request, response); - } - } -} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index f3e6a54568..1821f92fa4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -33,8 +33,6 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.base.Stopwatch; import com.google.common.base.Strings; import com.google.inject.Inject; @@ -68,8 +66,6 @@ import java.io.IOException; import java.util.Base64; import java.util.Enumeration; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index 3a1aba93e4..a2dccb30c9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -33,43 +33,30 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import sonia.scm.config.ScmConfiguration; -import sonia.scm.web.filter.ProviderPermissionFilter; +import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * Permission filter for mercurial repositories. * * @author Sebastian Sdorra */ -//@Priority(Filters.PRIORITY_AUTHORIZATION) -//@WebElement(value = HgServletModule.MAPPING_HG) -public class HgPermissionFilter extends ProviderPermissionFilter +public class HgPermissionFilter extends PermissionFilter { private static final Set READ_METHODS = ImmutableSet.of("GET", "HEAD", "OPTIONS", "TRACE"); - /** - * Constructs a new instance. - * - * @param configuration scm configuration - */ @Inject public HgPermissionFilter(ScmConfiguration configuration) { super(configuration); } - //~--- get methods ---------------------------------------------------------- - @Override public boolean isWriteRequest(HttpServletRequest request) { diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java index 21d1659bec..6c08d35897 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java @@ -33,8 +33,6 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.collect.ImmutableSet; import com.google.common.io.Closeables; import sonia.scm.repository.Repository; @@ -46,8 +44,6 @@ import java.io.IOException; import java.util.Collections; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java index eb52ba55f0..9f5ea234ce 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java @@ -32,67 +32,34 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.inject.Inject; import sonia.scm.plugin.Extension; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.web.SvnScmProtocolProviderWrapper; -/** - * - * @author Sebastian Sdorra - */ @Extension -public class SvnRepositoryServiceResolver implements RepositoryServiceResolver -{ +public class SvnRepositoryServiceResolver implements RepositoryServiceResolver { - /** Field description */ public static final String TYPE = "svn"; - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - * - * @param handler - * @param protocolWrapper - */ @Inject - public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper protocolWrapper) - { + public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper protocolWrapper) { this.handler = handler; this.protocolWrapper = protocolWrapper; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param repository - * - * @return - */ @Override - public SvnRepositoryServiceProvider resolve(Repository repository) - { + public SvnRepositoryServiceProvider resolve(Repository repository) { SvnRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) - { + if (TYPE.equalsIgnoreCase(repository.getType())) { provider = new SvnRepositoryServiceProvider(handler, repository, protocolWrapper.get(repository)); } return provider; } - //~--- fields --------------------------------------------------------------- - - /** Field description */ private SvnRepositoryHandler handler; private final InitializingHttpScmProtocolWrapper protocolWrapper; diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java deleted file mode 100644 index b5db32a449..0000000000 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. 2. Redistributions in - * binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. 3. Neither the name of SCM-Manager; - * nor the names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - - -package sonia.scm.web; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.inject.Inject; -import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.SvnUtil; -import sonia.scm.util.HttpUtil; -import sonia.scm.web.filter.AuthenticationFilter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -//~--- JDK imports ------------------------------------------------------------ - -/** - * - * @author Sebastian Sdorra - */ -//@Priority(Filters.PRIORITY_AUTHENTICATION) -//@WebElement(value = SvnServletModule.PATTERN_SVN) -public class SvnBasicAuthenticationFilter extends AuthenticationFilter -{ - - /** - * Constructs ... - * - * - * @param configuration - * @param webTokenGenerators - */ - @Inject - public SvnBasicAuthenticationFilter(ScmConfiguration configuration, Set webTokenGenerators) { - super(configuration, webTokenGenerators); - } - - //~--- methods -------------------------------------------------------------- - - /** - * Sends unauthorized instead of forbidden for svn clients, because the - * svn client prompts again for authentication. - * - * - * @param request http request - * @param response http response - * - * @throws IOException - */ - @Override - protected void sendFailedAuthenticationError(HttpServletRequest request, - HttpServletResponse response) - throws IOException - { - if (SvnUtil.isSvnClient(request)) - { - HttpUtil.sendUnauthorized(response, configuration.getRealmDescription()); - } - else - { - super.sendFailedAuthenticationError(request, response); - } - } -} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index 35b420257d..92d01db5a1 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -33,8 +33,6 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.inject.Inject; import com.google.inject.Singleton; import org.slf4j.Logger; @@ -55,8 +53,6 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 2939b44753..8918b8fa90 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -33,30 +33,24 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.ScmSvnErrorCode; import sonia.scm.repository.SvnUtil; -import sonia.scm.web.filter.ProviderPermissionFilter; +import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra */ -//@Priority(Filters.PRIORITY_AUTHORIZATION) -//@WebElement(value = SvnServletModule.PATTERN_SVN) -public class SvnPermissionFilter extends ProviderPermissionFilter +public class SvnPermissionFilter extends PermissionFilter { /** Field description */ diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 90ac29aa12..4f96059429 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -12,10 +12,11 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import java.util.Enumeration; -import static sonia.scm.web.SvnServletModule.PARAMETER_SVN_PARENTPATH; - @Singleton public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { + + public static final String PARAMETER_SVN_PARENTPATH = "SVNParentPath"; + @Inject public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { super(servletProvider, permissionFilter, uriInfoStore); @@ -24,14 +25,14 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr @Override protected void initializeServlet(ServletConfig config, ScmProviderHttpServlet httpServlet) throws ServletException { - super.initializeServlet(new X(config), httpServlet); + super.initializeServlet(new SvnConfigEnhancer(config), httpServlet); } - private static class X implements ServletConfig { + private static class SvnConfigEnhancer implements ServletConfig { private final ServletConfig originalConfig; - private X(ServletConfig originalConfig) { + private SvnConfigEnhancer(ServletConfig originalConfig) { this.originalConfig = originalConfig; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 9b9dc0bcb0..8526d6380a 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -33,43 +33,21 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.inject.servlet.ServletModule; import org.mapstruct.factory.Mappers; import sonia.scm.api.v2.resources.SvnConfigDtoToSvnConfigMapper; import sonia.scm.api.v2.resources.SvnConfigToSvnConfigDtoMapper; import sonia.scm.plugin.Extension; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra */ @Extension -public class SvnServletModule extends ServletModule -{ +public class SvnServletModule extends ServletModule { - /** Field description */ - public static final String PARAMETER_SVN_PARENTPATH = "SVNParentPath"; - - /** Field description */ - public static final String PATTERN_SVN = "/svn/*"; - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - */ @Override - protected void configureServlets() - { - filter(PATTERN_SVN).through(SvnGZipFilter.class); -// filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class); -// filter(PATTERN_SVN).through(SvnPermissionFilter.class); - + protected void configureServlets() { bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass()); bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass()); } diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index cb272de38f..5a087a1c70 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -33,8 +33,6 @@ package sonia.scm; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.base.Throwables; import com.google.common.collect.Lists; import com.google.inject.Injector; @@ -63,8 +61,6 @@ import java.util.Collections; import java.util.List; import java.util.Set; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 14fb8552f9..fd330a6d1d 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -33,8 +33,6 @@ package sonia.scm; -//~--- non-JDK imports -------------------------------------------------------- - import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Provider; import com.google.inject.multibindings.Multibinder; @@ -121,8 +119,6 @@ import sonia.scm.web.security.DefaultAdministrationContext; import javax.net.ssl.SSLContext; import javax.servlet.ServletContext; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra @@ -188,14 +184,6 @@ public class ScmServletModule extends ServletModule //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * - * @param servletContext - * @param pluginLoader - * @param overrides - */ ScmServletModule(ServletContext servletContext, DefaultPluginLoader pluginLoader, ClassOverrides overrides) { this.servletContext = servletContext; diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java index 59ffbe560b..6ad9b6257e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java @@ -33,8 +33,6 @@ package sonia.scm.api.rest.resources; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Maps; @@ -59,8 +57,6 @@ import java.util.Comparator; import java.util.List; import java.util.Map; -//~--- JDK imports ------------------------------------------------------------ - /** * * @author Sebastian Sdorra diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 8638c7e4e8..1ddfb4a3d3 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -31,8 +31,6 @@ package sonia.scm.repository; -//~--- non-JDK imports -------------------------------------------------------- - import com.github.sdorra.ssp.PermissionActionCheck; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -67,8 +65,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; -//~--- JDK imports ------------------------------------------------------------ - /** * Default implementation of {@link RepositoryManager}. * diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java index 3f061ff46d..62067db172 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryProvider.java @@ -33,30 +33,26 @@ package sonia.scm.repository; -//~--- non-JDK imports -------------------------------------------------------- - import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.servlet.RequestScoped; -import sonia.scm.security.ScmSecurityException; import javax.servlet.http.HttpServletRequest; -//~--- JDK imports ------------------------------------------------------------ - @RequestScoped public class DefaultRepositoryProvider implements RepositoryProvider { public static final String ATTRIBUTE_NAME = "scm.request.repository"; private final Provider requestProvider; + @Inject public DefaultRepositoryProvider(Provider requestProvider) { this.requestProvider = requestProvider; } @Override - public Repository get() throws ScmSecurityException { + public Repository get() { HttpServletRequest request = requestProvider.get(); if (request != null) { From c21612bd8ef152e325b64e66e2d238ea921f0464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 13:15:08 +0200 Subject: [PATCH 23/48] Fix permission git lfs integration test --- .../scm/web/filter/PermissionFilter.java | 30 +------------- .../api/v2/resources/UserToUserDtoMapper.java | 2 +- .../scm/web/protocol/HttpProtocolServlet.java | 1 + .../test/java/sonia/scm/it/GitLfsITCase.java | 40 ++++++++++++++++--- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index 3415c3e338..a01875fed0 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -33,7 +33,6 @@ package sonia.scm.web.filter; -import com.google.common.base.Splitter; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.subject.Subject; @@ -46,13 +45,11 @@ import sonia.scm.repository.RepositoryPermissions; import sonia.scm.security.Role; import sonia.scm.security.ScmSecurityException; import sonia.scm.util.HttpUtil; -import sonia.scm.util.Util; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Iterator; /** * Abstract http filter to check repository permissions. @@ -121,7 +118,7 @@ public abstract class PermissionFilter getActionAsString(writeRequest), repository.getName(), getUserName(subject)); - continuation.serve(); + continuation.doService(); } else { @@ -172,29 +169,6 @@ public abstract class PermissionFilter HttpUtil.sendUnauthorized(response, configuration.getRealmDescription()); } - /** - * Extracts the type of the repositroy from url. - * - * - * @param request http request - * - * @return type of repository - */ - private String extractType(HttpServletRequest request) - { - Iterator it = Splitter.on( - HttpUtil.SEPARATOR_PATH).omitEmptyStrings().split( - request.getRequestURI()).iterator(); - String type = it.next(); - - if (Util.isNotEmpty(request.getContextPath())) - { - type = it.next(); - } - - return type; - } - /** * Send access denied to the servlet response. * @@ -287,6 +261,6 @@ public abstract class PermissionFilter @FunctionalInterface public interface ContinuationServlet { - void serve() throws ServletException, IOException; + void doService() throws ServletException, IOException; } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserToUserDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserToUserDtoMapper.java index 00aba5a700..97a3a21482 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserToUserDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserToUserDtoMapper.java @@ -33,7 +33,7 @@ public abstract class UserToUserDtoMapper extends BaseMapper { } @AfterMapping - void appendLinks(User user, @MappingTarget UserDto target) { + protected void appendLinks(User user, @MappingTarget UserDto target) { Links.Builder linksBuilder = linkingTo().self(resourceLinks.user().self(target.getName())); if (UserPermissions.delete(user).isPermitted()) { linksBuilder.single(link("delete", resourceLinks.user().delete(target.getName()))); diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java index 7ba4d2392c..2a02afe7f6 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java @@ -56,6 +56,7 @@ public class HttpProtocolServlet extends HttpServlet { log.trace("dispatch browser request for user agent {}", userAgent); dispatcher.dispatch(request, response, request.getRequestURI()); } else { + String pathInfo = request.getPathInfo(); Optional namespaceAndName = namespaceAndNameFromPathExtractor.fromUri(pathInfo); if (namespaceAndName.isPresent()) { diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java index b07f0c6067..7da9b8adfb 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java @@ -36,34 +36,39 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; import com.google.common.base.Charsets; +import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.UniformInterfaceException; import org.apache.shiro.crypto.hash.Sha256Hash; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import sonia.scm.api.rest.ObjectMapperProvider; import sonia.scm.api.v2.resources.RepositoryDto; +import sonia.scm.api.v2.resources.UserDto; +import sonia.scm.api.v2.resources.UserToUserDtoMapperImpl; import sonia.scm.repository.PermissionType; import sonia.scm.repository.Repository; import sonia.scm.user.User; import sonia.scm.user.UserTestData; import sonia.scm.util.HttpUtil; +import sonia.scm.web.VndMediaType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import java.io.IOException; +import java.net.URI; import java.util.UUID; import static org.junit.Assert.assertArrayEquals; import static sonia.scm.it.IntegrationTestUtil.BASE_URL; import static sonia.scm.it.IntegrationTestUtil.REST_BASE_URL; import static sonia.scm.it.IntegrationTestUtil.createAdminClient; +import static sonia.scm.it.IntegrationTestUtil.createResource; import static sonia.scm.it.IntegrationTestUtil.readJson; import static sonia.scm.it.RepositoryITUtil.createRepository; import static sonia.scm.it.RepositoryITUtil.deleteRepository; @@ -112,7 +117,7 @@ public class GitLfsITCase { } @Test - @Ignore("permissions not yet implemented") +// @Ignore("permissions not yet implemented") public void testLfsAPIWithOwnerPermissions() throws IOException { uploadAndDownloadAsUser(PermissionType.OWNER); } @@ -126,6 +131,11 @@ public class GitLfsITCase { // TODO enable when permissions are implemented in v2 // repository.getPermissions().add(new Permission(trillian.getId(), permissionType)); // modifyRepository(repository); + String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); + IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) + .accept("*/*") + .type(VndMediaType.PERMISSION) + .post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"WRITE\"}"); ScmClient client = new ScmClient(trillian.getId(), "secret123"); @@ -136,13 +146,21 @@ public class GitLfsITCase { } @Test - @Ignore("permissions not yet implemented") +// @Ignore("permissions not yet implemented") public void testLfsAPIWithWritePermissions() throws IOException { uploadAndDownloadAsUser(PermissionType.WRITE); } private void createUser(User user) { - adminClient.resource(REST_BASE_URL + "users.json").post(user); + UserDto dto = new UserToUserDtoMapperImpl(){ + @Override + protected void appendLinks(User user, UserDto target) {} + }.map(user); + dto.setPassword(user.getPassword()); + createResource(adminClient, "users") + .accept("*/*") + .type(VndMediaType.USER) + .post(ClientResponse.class, dto); } private void modifyRepository(Repository repository) { @@ -154,7 +172,7 @@ public class GitLfsITCase { } @Test - @Ignore("permissions not yet implemented") +// @Ignore("permissions not yet implemented") public void testLfsAPIWithoutWritePermissions() throws IOException { User trillian = UserTestData.createTrillian(); trillian.setPassword("secret123"); @@ -168,6 +186,11 @@ public class GitLfsITCase { // TODO enable when permissions are implemented in v2 // repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ)); // modifyRepository(repository); + String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); + IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) + .accept("*/*") + .type(VndMediaType.PERMISSION) + .post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"READ\"}"); ScmClient client = new ScmClient(trillian.getId(), "secret123"); uploadAndDownload(client); @@ -177,7 +200,7 @@ public class GitLfsITCase { } @Test - @Ignore("permissions not yet implemented") +// @Ignore("permissions not yet implemented") public void testLfsDownloadWithReadPermissions() throws IOException { User trillian = UserTestData.createTrillian(); trillian.setPassword("secret123"); @@ -188,6 +211,11 @@ public class GitLfsITCase { // TODO enable when permissions are implemented in v2 // repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ)); // modifyRepository(repository); + String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); + IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) + .accept("*/*") + .type(VndMediaType.PERMISSION) + .post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"READ\"}"); // upload data as admin String data = UUID.randomUUID().toString(); From b3088fa7622eab080ea916f0f6053be55fe3f326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 14:28:07 +0200 Subject: [PATCH 24/48] Delete user after test --- .../test/java/sonia/scm/it/GitLfsITCase.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java index 7da9b8adfb..611a584485 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java @@ -51,7 +51,6 @@ import sonia.scm.api.v2.resources.RepositoryDto; import sonia.scm.api.v2.resources.UserDto; import sonia.scm.api.v2.resources.UserToUserDtoMapperImpl; import sonia.scm.repository.PermissionType; -import sonia.scm.repository.Repository; import sonia.scm.user.User; import sonia.scm.user.UserTestData; import sonia.scm.util.HttpUtil; @@ -117,7 +116,6 @@ public class GitLfsITCase { } @Test -// @Ignore("permissions not yet implemented") public void testLfsAPIWithOwnerPermissions() throws IOException { uploadAndDownloadAsUser(PermissionType.OWNER); } @@ -128,9 +126,6 @@ public class GitLfsITCase { createUser(trillian); try { - // TODO enable when permissions are implemented in v2 -// repository.getPermissions().add(new Permission(trillian.getId(), permissionType)); -// modifyRepository(repository); String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) .accept("*/*") @@ -146,7 +141,6 @@ public class GitLfsITCase { } @Test -// @Ignore("permissions not yet implemented") public void testLfsAPIWithWritePermissions() throws IOException { uploadAndDownloadAsUser(PermissionType.WRITE); } @@ -163,16 +157,11 @@ public class GitLfsITCase { .post(ClientResponse.class, dto); } - private void modifyRepository(Repository repository) { - adminClient.resource(REST_BASE_URL + "repositories/" + repository.getId() + ".json").put(repository); - } - private void removeUser(User user) { - adminClient.resource(REST_BASE_URL + "users/" + user.getId() + ".json").delete(); + adminClient.resource(REST_BASE_URL + "users/" + user.getId()).delete(); } @Test -// @Ignore("permissions not yet implemented") public void testLfsAPIWithoutWritePermissions() throws IOException { User trillian = UserTestData.createTrillian(); trillian.setPassword("secret123"); @@ -183,9 +172,6 @@ public class GitLfsITCase { try { - // TODO enable when permissions are implemented in v2 -// repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ)); -// modifyRepository(repository); String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) .accept("*/*") @@ -200,7 +186,6 @@ public class GitLfsITCase { } @Test -// @Ignore("permissions not yet implemented") public void testLfsDownloadWithReadPermissions() throws IOException { User trillian = UserTestData.createTrillian(); trillian.setPassword("secret123"); @@ -208,9 +193,6 @@ public class GitLfsITCase { try { - // TODO enable when permissions are implemented in v2 -// repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ)); -// modifyRepository(repository); String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref(); IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl)) .accept("*/*") From 5b35fb2372515f45f336a13de5452119b2498c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 16:03:32 +0200 Subject: [PATCH 25/48] Fallback to configured base url if UriInfoStore not set --- .../scm/repository/spi/HttpScmProtocol.java | 9 ++--- .../InitializingHttpScmProtocolWrapper.java | 16 +++++++- .../repository/api/RepositoryServiceTest.java | 3 +- .../repository/spi/HttpScmProtocolTest.java | 40 +++++++++++++++++++ .../web/GitScmProtocolProviderWrapper.java | 5 ++- .../scm/web/HgScmProtocolProviderWrapper.java | 5 ++- .../web/SvnScmProtocolProviderWrapper.java | 5 ++- 7 files changed, 68 insertions(+), 15 deletions(-) create mode 100644 scm-core/src/test/java/sonia/scm/repository/spi/HttpScmProtocolTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java index b93deba10a..7ec47ea284 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java @@ -7,18 +7,17 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.net.URI; public abstract class HttpScmProtocol implements ScmProtocol { private final Repository repository; - private final UriInfo uriInfo; + private final String basePath; - public HttpScmProtocol(Repository repository, UriInfo uriInfo) { + public HttpScmProtocol(Repository repository, String basePath) { this.repository = repository; - this.uriInfo = uriInfo; + this.basePath = basePath; } @Override @@ -28,7 +27,7 @@ public abstract class HttpScmProtocol implements ScmProtocol { @Override public String getUrl() { - return uriInfo.getBaseUri().resolve(URI.create("../../repo/" + repository.getNamespace() + "/" + repository.getName())).toASCIIString(); + return URI.create(basePath + "/").resolve("repo/" + repository.getNamespace() + "/" + repository.getName()).toASCIIString(); } public final void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException { diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 3d4d3c6205..b54b5c812c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -3,6 +3,7 @@ package sonia.scm.repository.spi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; import sonia.scm.web.filter.PermissionFilter; @@ -21,14 +22,16 @@ public abstract class InitializingHttpScmProtocolWrapper { private final Provider delegateProvider; private final Provider permissionFilterProvider; private final Provider uriInfoStore; + private final ScmConfiguration scmConfiguration; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { this.delegateProvider = delegateProvider; this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; + this.scmConfiguration = scmConfiguration; } protected void initializeServlet(ServletConfig config, ScmProviderHttpServlet httpServlet) throws ServletException { @@ -39,10 +42,18 @@ public abstract class InitializingHttpScmProtocolWrapper { return new ProtocolWrapper(repository); } + private String computeBasePath() { + if (uriInfoStore.get() != null) { + return uriInfoStore.get().get().getBaseUri().resolve("../..").toASCIIString(); + } else { + return scmConfiguration.getBaseUrl(); + } + } + private class ProtocolWrapper extends HttpScmProtocol { public ProtocolWrapper(Repository repository) { - super(repository, uriInfoStore.get().get()); + super(repository, computeBasePath()); } @Override @@ -63,5 +74,6 @@ public abstract class InitializingHttpScmProtocolWrapper { repository, () -> delegateProvider.get().service(request, response, repository)); } + } } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index 1783d17936..9cb398b571 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -8,7 +8,6 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.util.Collection; import java.util.Collections; @@ -46,7 +45,7 @@ public class RepositoryServiceTest { private static class DummyHttpProtocol extends HttpScmProtocol { public DummyHttpProtocol(Repository repository) { - super(repository, mock(UriInfo.class)); + super(repository, ""); } @Override diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/HttpScmProtocolTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/HttpScmProtocolTest.java new file mode 100644 index 0000000000..1fd772fee3 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/spi/HttpScmProtocolTest.java @@ -0,0 +1,40 @@ +package sonia.scm.repository.spi; + +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import sonia.scm.repository.Repository; + +import javax.servlet.ServletConfig; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class HttpScmProtocolTest { + + @TestFactory + Stream shouldCreateCorrectUrlsWithContextPath() { + return Stream.of("http://localhost/scm", "http://localhost/scm/") + .map(url -> assertResultingUrl(url, "http://localhost/scm/repo/space/name")); + } + + @TestFactory + Stream shouldCreateCorrectUrlsWithPort() { + return Stream.of("http://localhost:8080", "http://localhost:8080/") + .map(url -> assertResultingUrl(url, "http://localhost:8080/repo/space/name")); + } + + DynamicTest assertResultingUrl(String baseUrl, String expectedUrl) { + String actualUrl = createInstanceOfHttpScmProtocol(baseUrl).getUrl(); + return DynamicTest.dynamicTest(baseUrl + " -> " + expectedUrl, () -> assertThat(actualUrl).isEqualTo(expectedUrl)); + } + + private HttpScmProtocol createInstanceOfHttpScmProtocol(String baseUrl) { + return new HttpScmProtocol(new Repository("", "", "space", "name"), baseUrl) { + @Override + protected void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) { + } + }; + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index ae378c2439..cda8431283 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -1,6 +1,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -10,7 +11,7 @@ import javax.inject.Singleton; @Singleton public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { - super(servletProvider, permissionFilter, uriInfoStore); + public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index ba5c40e7f9..9cb22363ce 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -1,6 +1,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -10,7 +11,7 @@ import javax.inject.Singleton; @Singleton public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { - super(servletProvider, permissionFilter, uriInfoStore); + public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 4f96059429..99f5b42fb2 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -1,6 +1,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import sonia.scm.repository.spi.ScmProviderHttpServlet; @@ -18,8 +19,8 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr public static final String PARAMETER_SVN_PARENTPATH = "SVNParentPath"; @Inject - public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore) { - super(servletProvider, permissionFilter, uriInfoStore); + public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } @Override From e5e3e678ad3c3a922aa1bccf618e54377f0e99ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 11 Sep 2018 16:26:20 +0200 Subject: [PATCH 26/48] Correct check for set UriInfo --- .../repository/spi/InitializingHttpScmProtocolWrapper.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index b54b5c812c..6e6a3cb512 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,7 +1,5 @@ package sonia.scm.repository.spi; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.UriInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; @@ -16,9 +14,6 @@ import java.io.IOException; public abstract class InitializingHttpScmProtocolWrapper { - private static final Logger logger = - LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); - private final Provider delegateProvider; private final Provider permissionFilterProvider; private final Provider uriInfoStore; @@ -43,7 +38,7 @@ public abstract class InitializingHttpScmProtocolWrapper { } private String computeBasePath() { - if (uriInfoStore.get() != null) { + if (uriInfoStore.get() != null && uriInfoStore.get().get() != null) { return uriInfoStore.get().get().getBaseUri().resolve("../..").toASCIIString(); } else { return scmConfiguration.getBaseUrl(); From f718a2ba4c2cdc4e7030558824a076a4b6095464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 08:40:41 +0200 Subject: [PATCH 27/48] Remove direct dependency to UriInfo --- .../scm/api/v2/resources/LinkBuilder.java | 9 ++--- .../scm/api/v2/resources/ScmPathInfo.java | 7 ++++ .../scm/api/v2/resources/UriInfoStore.java | 5 ++- .../InitializingHttpScmProtocolWrapper.java | 2 +- .../v2/resources/GitConfigResourceTest.java | 2 +- .../GitConfigToGitConfigDtoMapperTest.java | 2 +- .../HgConfigInstallationsResourceTest.java | 2 +- .../HgConfigInstallationsToDtoMapperTest.java | 2 +- .../HgConfigPackageResourceTest.java | 2 +- .../HgConfigPackagesToDtoMapperTest.java | 5 +-- .../v2/resources/HgConfigResourceTest.java | 2 +- .../HgConfigToHgConfigDtoMapperTest.java | 2 +- .../v2/resources/SvnConfigResourceTest.java | 2 +- .../SvnConfigToSvnConfigDtoMapperTest.java | 2 +- .../scm/api/v2/resources/ResourceLinks.java | 39 +++++++++---------- .../scm/api/v2/resources/LinkBuilderTest.java | 5 +-- .../scm/api/v2/resources/MeResourceTest.java | 5 +-- .../resources/RepositoryRootResourceTest.java | 5 +-- .../RepositoryToRepositoryDtoMapperTest.java | 5 +-- .../api/v2/resources/ResourceLinksMock.java | 5 +-- .../api/v2/resources/ResourceLinksTest.java | 5 +-- .../api/v2/resources/UriInfoStoreTest.java | 9 ++++- 22 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java index 6f6831b058..13ae04b093 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java @@ -3,7 +3,6 @@ package sonia.scm.api.v2.resources; import com.google.common.collect.ImmutableList; import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; import java.net.URI; import java.util.Arrays; @@ -25,15 +24,15 @@ import java.util.Arrays; */ @SuppressWarnings("WeakerAccess") // Non-public will result in IllegalAccessError for plugins public class LinkBuilder { - private final UriInfo uriInfo; + private final ScmPathInfo uriInfo; private final Class[] classes; private final ImmutableList calls; - public LinkBuilder(UriInfo uriInfo, Class... classes) { + public LinkBuilder(ScmPathInfo uriInfo, Class... classes) { this(uriInfo, classes, ImmutableList.of()); } - private LinkBuilder(UriInfo uriInfo, Class[] classes, ImmutableList calls) { + private LinkBuilder(ScmPathInfo uriInfo, Class[] classes, ImmutableList calls) { this.uriInfo = uriInfo; this.classes = classes; this.calls = calls; @@ -51,7 +50,7 @@ public class LinkBuilder { throw new IllegalStateException("not enough methods for all classes"); } - URI baseUri = uriInfo.getBaseUri(); + URI baseUri = uriInfo.getApiRestUri(); URI relativeUri = createRelativeUri(); return baseUri.resolve(relativeUri); } diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java new file mode 100644 index 0000000000..0afb379eed --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java @@ -0,0 +1,7 @@ +package sonia.scm.api.v2.resources; + +import java.net.URI; + +public interface ScmPathInfo { + URI getApiRestUri(); +} diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java index 2f61383cfd..5193ea6937 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java @@ -6,8 +6,8 @@ public class UriInfoStore { private UriInfo uriInfo; - public UriInfo get() { - return uriInfo; + public ScmPathInfo get() { + return () -> uriInfo.getBaseUri(); } public void set(UriInfo uriInfo) { @@ -16,4 +16,5 @@ public class UriInfoStore { } this.uriInfo = uriInfo; } + } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 6e6a3cb512..651e4b3a7d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -39,7 +39,7 @@ public abstract class InitializingHttpScmProtocolWrapper { private String computeBasePath() { if (uriInfoStore.get() != null && uriInfoStore.get().get() != null) { - return uriInfoStore.get().get().getBaseUri().resolve("../..").toASCIIString(); + return uriInfoStore.get().get().getApiRestUri().resolve("../..").toASCIIString(); } else { return scmConfiguration.getBaseUrl(); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java index 42790ea7a4..44603a65d3 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java @@ -67,7 +67,7 @@ public class GitConfigResourceTest { when(repositoryHandler.getConfig()).thenReturn(gitConfig); GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java index 51fded4839..903ee4e653 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java @@ -40,7 +40,7 @@ public class GitConfigToGitConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(GitConfigResource.GIT_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java index 540a5b6757..748b2c1b6e 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java @@ -61,7 +61,7 @@ public class HgConfigInstallationsResourceTest { new HgConfigResource(null, null, null, null, null, resourceProvider)); - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java index 34048f80b2..fcc90ee4e6 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java @@ -34,7 +34,7 @@ public class HgConfigInstallationsToDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2 + "/installations/" + expectedPath); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java index 044897ad80..f24b30f515 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java @@ -81,7 +81,7 @@ public class HgConfigPackageResourceTest { public void prepareEnvironment() { setupResources(); - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); when(hgPackageReader.getPackages().getPackages()).thenReturn(createPackages()); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java index 671d9fb7e1..0773499462 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java @@ -1,6 +1,5 @@ package sonia.scm.api.v2.resources; -import de.otto.edison.hal.HalRepresentation; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -13,12 +12,10 @@ import sonia.scm.installer.HgPackages; import java.net.URI; import java.util.Arrays; -import java.util.Collection; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import static sonia.scm.api.v2.resources.HgConfigTests.assertEqualsPackage; import static sonia.scm.api.v2.resources.HgConfigTests.createPackage; @@ -38,7 +35,7 @@ public class HgConfigPackagesToDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2 + "/packages"); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java index 11a0fb55f9..aa29603ff1 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java @@ -79,7 +79,7 @@ public class HgConfigResourceTest { new HgConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, packagesResource, autoconfigResource, installationsResource); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java index a12e95926c..3f22c12f86 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java @@ -41,7 +41,7 @@ public class HgConfigToHgConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java index de4d654910..67f3e47950 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java @@ -67,7 +67,7 @@ public class SvnConfigResourceTest { when(repositoryHandler.getConfig()).thenReturn(gitConfig); SvnConfigResource gitConfigResource = new SvnConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java index de7b0ecd31..cfe2c59772 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java @@ -42,7 +42,7 @@ public class SvnConfigToSvnConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(SvnConfigResource.SVN_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java index 11258745a8..7059ea257d 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java @@ -3,7 +3,6 @@ package sonia.scm.api.v2.resources; import sonia.scm.repository.NamespaceAndName; import javax.inject.Inject; -import javax.ws.rs.core.UriInfo; import java.net.URI; class ResourceLinks { @@ -23,7 +22,7 @@ class ResourceLinks { static class GroupLinks { private final LinkBuilder groupLinkBuilder; - GroupLinks(UriInfo uriInfo) { + GroupLinks(ScmPathInfo uriInfo) { groupLinkBuilder = new LinkBuilder(uriInfo, GroupRootResource.class, GroupResource.class); } @@ -47,7 +46,7 @@ class ResourceLinks { static class GroupCollectionLinks { private final LinkBuilder collectionLinkBuilder; - GroupCollectionLinks(UriInfo uriInfo) { + GroupCollectionLinks(ScmPathInfo uriInfo) { collectionLinkBuilder = new LinkBuilder(uriInfo, GroupRootResource.class, GroupCollectionResource.class); } @@ -67,7 +66,7 @@ class ResourceLinks { static class UserLinks { private final LinkBuilder userLinkBuilder; - UserLinks(UriInfo uriInfo) { + UserLinks(ScmPathInfo uriInfo) { userLinkBuilder = new LinkBuilder(uriInfo, UserRootResource.class, UserResource.class); } @@ -91,7 +90,7 @@ class ResourceLinks { static class UserCollectionLinks { private final LinkBuilder collectionLinkBuilder; - UserCollectionLinks(UriInfo uriInfo) { + UserCollectionLinks(ScmPathInfo uriInfo) { collectionLinkBuilder = new LinkBuilder(uriInfo, UserRootResource.class, UserCollectionResource.class); } @@ -111,7 +110,7 @@ class ResourceLinks { static class ConfigLinks { private final LinkBuilder configLinkBuilder; - ConfigLinks(UriInfo uriInfo) { + ConfigLinks(ScmPathInfo uriInfo) { configLinkBuilder = new LinkBuilder(uriInfo, ConfigResource.class); } @@ -130,9 +129,9 @@ class ResourceLinks { static class RepositoryLinks { private final LinkBuilder repositoryLinkBuilder; - private final UriInfo uriInfo; + private final ScmPathInfo uriInfo; - RepositoryLinks(UriInfo uriInfo) { + RepositoryLinks(ScmPathInfo uriInfo) { repositoryLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class); this.uriInfo = uriInfo; } @@ -157,7 +156,7 @@ class ResourceLinks { static class RepositoryCollectionLinks { private final LinkBuilder collectionLinkBuilder; - RepositoryCollectionLinks(UriInfo uriInfo) { + RepositoryCollectionLinks(ScmPathInfo uriInfo) { collectionLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryCollectionResource.class); } @@ -177,7 +176,7 @@ class ResourceLinks { static class RepositoryTypeLinks { private final LinkBuilder repositoryTypeLinkBuilder; - RepositoryTypeLinks(UriInfo uriInfo) { + RepositoryTypeLinks(ScmPathInfo uriInfo) { repositoryTypeLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeResource.class); } @@ -193,7 +192,7 @@ class ResourceLinks { static class RepositoryTypeCollectionLinks { private final LinkBuilder collectionLinkBuilder; - RepositoryTypeCollectionLinks(UriInfo uriInfo) { + RepositoryTypeCollectionLinks(ScmPathInfo uriInfo) { collectionLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeCollectionResource.class); } @@ -210,7 +209,7 @@ class ResourceLinks { static class TagCollectionLinks { private final LinkBuilder tagLinkBuilder; - TagCollectionLinks(UriInfo uriInfo) { + TagCollectionLinks(ScmPathInfo uriInfo) { tagLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, TagRootResource.class); } @@ -230,7 +229,7 @@ class ResourceLinks { static class DiffLinks { private final LinkBuilder diffLinkBuilder; - DiffLinks(UriInfo uriInfo) { + DiffLinks(ScmPathInfo uriInfo) { diffLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, DiffRootResource.class); } @@ -250,7 +249,7 @@ class ResourceLinks { static class BranchLinks { private final LinkBuilder branchLinkBuilder; - BranchLinks(UriInfo uriInfo) { + BranchLinks(ScmPathInfo uriInfo) { branchLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class); } @@ -270,7 +269,7 @@ class ResourceLinks { static class BranchCollectionLinks { private final LinkBuilder branchLinkBuilder; - BranchCollectionLinks(UriInfo uriInfo) { + BranchCollectionLinks(ScmPathInfo uriInfo) { branchLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class); } @@ -286,7 +285,7 @@ class ResourceLinks { static class ChangesetLinks { private final LinkBuilder changesetLinkBuilder; - ChangesetLinks(UriInfo uriInfo) { + ChangesetLinks(ScmPathInfo uriInfo) { changesetLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, ChangesetRootResource.class); } @@ -310,7 +309,7 @@ class ResourceLinks { static class SourceLinks { private final LinkBuilder sourceLinkBuilder; - SourceLinks(UriInfo uriInfo) { + SourceLinks(ScmPathInfo uriInfo) { sourceLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, SourceRootResource.class); } @@ -346,7 +345,7 @@ class ResourceLinks { static class PermissionLinks { private final LinkBuilder permissionLinkBuilder; - PermissionLinks(UriInfo uriInfo) { + PermissionLinks(ScmPathInfo uriInfo) { permissionLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, PermissionRootResource.class); } @@ -383,7 +382,7 @@ class ResourceLinks { static class UIPluginLinks { private final LinkBuilder uiPluginLinkBuilder; - UIPluginLinks(UriInfo uriInfo) { + UIPluginLinks(ScmPathInfo uriInfo) { uiPluginLinkBuilder = new LinkBuilder(uriInfo, UIRootResource.class, UIPluginResource.class); } @@ -399,7 +398,7 @@ class ResourceLinks { static class UIPluginCollectionLinks { private final LinkBuilder uiPluginCollectionLinkBuilder; - UIPluginCollectionLinks(UriInfo uriInfo) { + UIPluginCollectionLinks(ScmPathInfo uriInfo) { uiPluginCollectionLinkBuilder = new LinkBuilder(uriInfo, UIRootResource.class, UIPluginResource.class); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/LinkBuilderTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/LinkBuilderTest.java index 37c584dfdf..c84e1a21a7 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/LinkBuilderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/LinkBuilderTest.java @@ -4,7 +4,6 @@ import org.junit.Before; import org.junit.Test; import javax.ws.rs.Path; -import javax.ws.rs.core.UriInfo; import java.net.URI; import java.net.URISyntaxException; @@ -37,7 +36,7 @@ public class LinkBuilderTest { } } - private UriInfo uriInfo = mock(UriInfo.class); + private ScmPathInfo uriInfo = mock(ScmPathInfo.class); @Test public void shouldBuildSimplePath() { @@ -94,6 +93,6 @@ public class LinkBuilderTest { @Before public void setBaseUri() throws URISyntaxException { - when(uriInfo.getBaseUri()).thenReturn(new URI("http://example.com/")); + when(uriInfo.getApiRestUri()).thenReturn(new URI("http://example.com/")); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java index 09dd545eb5..0040e8b45e 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java @@ -17,7 +17,6 @@ import sonia.scm.user.UserManager; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.net.URI; import java.net.URISyntaxException; @@ -40,7 +39,7 @@ public class MeResourceTest { private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/")); @Mock - private UriInfo uriInfo; + private ScmPathInfo uriInfo; @Mock private UriInfoStore uriInfoStore; @@ -62,7 +61,7 @@ public class MeResourceTest { userToDtoMapper.setResourceLinks(resourceLinks); MeResource meResource = new MeResource(userToDtoMapper, userManager); dispatcher.getRegistry().addSingletonResource(meResource); - when(uriInfo.getBaseUri()).thenReturn(URI.create("/")); + when(uriInfo.getApiRestUri()).thenReturn(URI.create("/")); when(uriInfoStore.get()).thenReturn(uriInfo); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index 609ff282af..9fdef26d13 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -24,7 +24,6 @@ import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -73,7 +72,7 @@ public class RepositoryRootResourceTest { @Mock private UriInfoStore uriInfoStore; @Mock - private UriInfo uriInfo; + private ScmPathInfo uriInfo; private final URI baseUri = URI.create("/"); @@ -93,7 +92,7 @@ public class RepositoryRootResourceTest { RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider.of(repositoryResource), MockProvider.of(repositoryCollectionResource)); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(uriInfoStore.get()).thenReturn(uriInfo); - when(uriInfo.getBaseUri()).thenReturn(URI.create("/x/y")); + when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); dispatcher = createDispatcher(repositoryRootResource); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java index b77ad958c3..250da56908 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java @@ -18,7 +18,6 @@ import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.ScmProtocol; -import javax.ws.rs.core.UriInfo; import java.net.URI; import static java.util.Arrays.asList; @@ -51,7 +50,7 @@ public class RepositoryToRepositoryDtoMapperTest { @Mock private UriInfoStore uriInfoStore; @Mock - private UriInfo uriInfo; + private ScmPathInfo uriInfo; @InjectMocks private RepositoryToRepositoryDtoMapperImpl mapper; @@ -63,7 +62,7 @@ public class RepositoryToRepositoryDtoMapperTest { when(repositoryService.isSupported(any(Command.class))).thenReturn(true); when(repositoryService.getSupportedProtocols()).thenReturn(emptySet()); when(uriInfoStore.get()).thenReturn(uriInfo); - when(uriInfo.getBaseUri()).thenReturn(URI.create("/x/y")); + when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); } @After diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksMock.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksMock.java index f9ace9f8f6..1df652ea26 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksMock.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksMock.java @@ -1,6 +1,5 @@ package sonia.scm.api.v2.resources; -import javax.ws.rs.core.UriInfo; import java.net.URI; import static org.mockito.Mockito.mock; @@ -10,8 +9,8 @@ public class ResourceLinksMock { public static ResourceLinks createMock(URI baseUri) { ResourceLinks resourceLinks = mock(ResourceLinks.class); - UriInfo uriInfo = mock(UriInfo.class); - when(uriInfo.getBaseUri()).thenReturn(baseUri); + ScmPathInfo uriInfo = mock(ScmPathInfo.class); + when(uriInfo.getApiRestUri()).thenReturn(baseUri); when(resourceLinks.user()).thenReturn(new ResourceLinks.UserLinks(uriInfo)); when(resourceLinks.userCollection()).thenReturn(new ResourceLinks.UserCollectionLinks(uriInfo)); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksTest.java index a9209828c3..0f33476436 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ResourceLinksTest.java @@ -6,7 +6,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import sonia.scm.repository.NamespaceAndName; -import javax.ws.rs.core.UriInfo; import java.net.URI; import static org.junit.Assert.assertEquals; @@ -20,7 +19,7 @@ public class ResourceLinksTest { @Mock private UriInfoStore uriInfoStore; @Mock - private UriInfo uriInfo; + private ScmPathInfo uriInfo; @InjectMocks private ResourceLinks resourceLinks; @@ -178,6 +177,6 @@ public class ResourceLinksTest { public void initUriInfo() { initMocks(this); when(uriInfoStore.get()).thenReturn(uriInfo); - when(uriInfo.getBaseUri()).thenReturn(URI.create(BASE_URL)); + when(uriInfo.getApiRestUri()).thenReturn(URI.create(BASE_URL)); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UriInfoStoreTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UriInfoStoreTest.java index 559e701ae3..da0682c640 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UriInfoStoreTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UriInfoStoreTest.java @@ -4,19 +4,26 @@ import org.junit.Test; import javax.ws.rs.core.UriInfo; +import java.net.URI; + import static org.junit.Assert.assertSame; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class UriInfoStoreTest { @Test public void shouldReturnSetInfo() { + URI someUri = URI.create("/anything"); + UriInfo uriInfo = mock(UriInfo.class); UriInfoStore uriInfoStore = new UriInfoStore(); + when(uriInfo.getBaseUri()).thenReturn(someUri); + uriInfoStore.set(uriInfo); - assertSame(uriInfo, uriInfoStore.get()); + assertSame(someUri, uriInfoStore.get().getApiRestUri()); } @Test(expected = IllegalStateException.class) From 7c09f35ac8856d967042569d7c6236bbb883001e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 08:53:15 +0200 Subject: [PATCH 28/48] Rename UriInfoStore to ScmPathInfoStore --- ...riInfoStore.java => ScmPathInfoStore.java} | 2 +- .../InitializingHttpScmProtocolWrapper.java | 6 +-- .../GitConfigToGitConfigDtoMapper.java | 6 +-- .../web/GitScmProtocolProviderWrapper.java | 4 +- .../v2/resources/GitConfigResourceTest.java | 4 +- .../GitConfigToGitConfigDtoMapperTest.java | 4 +- .../HgConfigInstallationsToDtoMapper.java | 8 ++-- .../HgConfigPackagesToDtoMapper.java | 4 +- .../HgConfigToHgConfigDtoMapper.java | 6 +-- .../scm/web/HgScmProtocolProviderWrapper.java | 4 +- .../HgConfigInstallationsResourceTest.java | 4 +- .../HgConfigInstallationsToDtoMapperTest.java | 4 +- .../HgConfigPackageResourceTest.java | 4 +- .../HgConfigPackagesToDtoMapperTest.java | 4 +- .../v2/resources/HgConfigResourceTest.java | 4 +- .../HgConfigToHgConfigDtoMapperTest.java | 4 +- .../SvnConfigToSvnConfigDtoMapper.java | 6 +-- .../web/SvnScmProtocolProviderWrapper.java | 4 +- .../v2/resources/SvnConfigResourceTest.java | 4 +- .../SvnConfigToSvnConfigDtoMapperTest.java | 4 +- .../sonia/scm/api/rest/UriInfoFilter.java | 6 +-- .../scm/api/v2/resources/MapperModule.java | 2 +- .../RepositoryToRepositoryDtoMapper.java | 2 +- .../scm/api/v2/resources/ResourceLinks.java | 42 +++++++++---------- .../GroupCollectionToDtoMapperTest.java | 6 +-- .../scm/api/v2/resources/MeResourceTest.java | 4 +- .../resources/RepositoryRootResourceTest.java | 4 +- .../RepositoryToRepositoryDtoMapperTest.java | 4 +- .../api/v2/resources/ResourceLinksTest.java | 4 +- ...oreTest.java => ScmPathInfoStoreTest.java} | 15 ++++--- 30 files changed, 89 insertions(+), 90 deletions(-) rename scm-core/src/main/java/sonia/scm/api/v2/resources/{UriInfoStore.java => ScmPathInfoStore.java} (91%) rename scm-webapp/src/test/java/sonia/scm/api/v2/resources/{UriInfoStoreTest.java => ScmPathInfoStoreTest.java} (63%) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java similarity index 91% rename from scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java rename to scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java index 5193ea6937..caa1183378 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/UriInfoStore.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java @@ -2,7 +2,7 @@ package sonia.scm.api.v2.resources; import javax.ws.rs.core.UriInfo; -public class UriInfoStore { +public class ScmPathInfoStore { private UriInfo uriInfo; diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 651e4b3a7d..450f1d4495 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,6 +1,6 @@ package sonia.scm.repository.spi; -import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; import sonia.scm.web.filter.PermissionFilter; @@ -16,13 +16,13 @@ public abstract class InitializingHttpScmProtocolWrapper { private final Provider delegateProvider; private final Provider permissionFilterProvider; - private final Provider uriInfoStore; + private final Provider uriInfoStore; private final ScmConfiguration scmConfiguration; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { this.delegateProvider = delegateProvider; this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapper.java index 7163497487..7607b31faf 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapper.java @@ -18,7 +18,7 @@ import static de.otto.edison.hal.Links.linkingTo; public abstract class GitConfigToGitConfigDtoMapper extends BaseMapper { @Inject - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @AfterMapping void appendLinks(GitConfig config, @MappingTarget GitConfigDto target) { @@ -30,12 +30,12 @@ public abstract class GitConfigToGitConfigDtoMapper extends BaseMapper servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java index 44603a65d3..1ebe7fc98b 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java @@ -53,7 +53,7 @@ public class GitConfigResourceTest { private GitConfigDtoToGitConfigMapperImpl dtoToConfigMapper; @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private GitConfigToGitConfigDtoMapperImpl configToDtoMapper; @@ -67,7 +67,7 @@ public class GitConfigResourceTest { when(repositoryHandler.getConfig()).thenReturn(gitConfig); GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java index 903ee4e653..82c85029a3 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigToGitConfigDtoMapperTest.java @@ -28,7 +28,7 @@ public class GitConfigToGitConfigDtoMapperTest { private URI baseUri = URI.create("http://example.com/base/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private GitConfigToGitConfigDtoMapperImpl mapper; @@ -40,7 +40,7 @@ public class GitConfigToGitConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(GitConfigResource.GIT_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java index d2f4aecf7e..da980f75c0 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java @@ -8,11 +8,11 @@ import static de.otto.edison.hal.Links.linkingTo; public class HgConfigInstallationsToDtoMapper { - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @Inject - public HgConfigInstallationsToDtoMapper(UriInfoStore uriInfoStore) { - this.uriInfoStore = uriInfoStore; + public HgConfigInstallationsToDtoMapper(ScmPathInfoStore scmPathInfoStore) { + this.scmPathInfoStore = scmPathInfoStore; } public HgConfigInstallationsDto map(List installations, String path) { @@ -20,7 +20,7 @@ public class HgConfigInstallationsToDtoMapper { } private String createSelfLink(String path) { - LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), HgConfigResource.class); + LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), HgConfigResource.class); return linkBuilder.method("getInstallationsResource").parameters().href() + '/' + path; } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapper.java index 67d7e58dff..3ee87cef84 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapper.java @@ -20,7 +20,7 @@ import static de.otto.edison.hal.Links.linkingTo; public abstract class HgConfigPackagesToDtoMapper { @Inject - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; public HgConfigPackagesDto map(HgPackages hgpackages) { return map(new HgPackagesNonIterable(hgpackages)); @@ -40,7 +40,7 @@ public abstract class HgConfigPackagesToDtoMapper { } private String createSelfLink() { - LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), HgConfigResource.class); + LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), HgConfigResource.class); return linkBuilder.method("getPackagesResource").parameters().href(); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapper.java index 98137aebd5..b2a67e2aa4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapper.java @@ -18,7 +18,7 @@ import static de.otto.edison.hal.Links.linkingTo; public abstract class HgConfigToHgConfigDtoMapper extends BaseMapper { @Inject - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @AfterMapping void appendLinks(HgConfig config, @MappingTarget HgConfigDto target) { @@ -30,12 +30,12 @@ public abstract class HgConfigToHgConfigDtoMapper extends BaseMapper servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java index 748b2c1b6e..65b9c262cb 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java @@ -43,7 +43,7 @@ public class HgConfigInstallationsResourceTest { private final URI baseUri = URI.create("/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigInstallationsToDtoMapper mapper; @@ -61,7 +61,7 @@ public class HgConfigInstallationsResourceTest { new HgConfigResource(null, null, null, null, null, resourceProvider)); - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java index fcc90ee4e6..7cae1d9f7e 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java @@ -23,7 +23,7 @@ public class HgConfigInstallationsToDtoMapperTest { private URI baseUri = URI.create("http://example.com/base/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigInstallationsToDtoMapper mapper; @@ -34,7 +34,7 @@ public class HgConfigInstallationsToDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2 + "/installations/" + expectedPath); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java index f24b30f515..f1558b6efb 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java @@ -57,7 +57,7 @@ public class HgConfigPackageResourceTest { private final URI baseUri = java.net.URI.create("/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigPackagesToDtoMapperImpl mapper; @@ -81,7 +81,7 @@ public class HgConfigPackageResourceTest { public void prepareEnvironment() { setupResources(); - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); when(hgPackageReader.getPackages().getPackages()).thenReturn(createPackages()); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java index 0773499462..c4431da6d5 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackagesToDtoMapperTest.java @@ -26,7 +26,7 @@ public class HgConfigPackagesToDtoMapperTest { private URI baseUri = URI.create("http://example.com/base/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigPackagesToDtoMapperImpl mapper; @@ -35,7 +35,7 @@ public class HgConfigPackagesToDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2 + "/packages"); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java index aa29603ff1..9cd04a0789 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java @@ -54,7 +54,7 @@ public class HgConfigResourceTest { private HgConfigDtoToHgConfigMapperImpl dtoToConfigMapper; @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigToHgConfigDtoMapperImpl configToDtoMapper; @@ -79,7 +79,7 @@ public class HgConfigResourceTest { new HgConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, packagesResource, autoconfigResource, installationsResource); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java index 3f22c12f86..81c50f3d58 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigToHgConfigDtoMapperTest.java @@ -29,7 +29,7 @@ public class HgConfigToHgConfigDtoMapperTest { private URI baseUri = URI.create("http://example.com/base/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private HgConfigToHgConfigDtoMapperImpl mapper; @@ -41,7 +41,7 @@ public class HgConfigToHgConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java index a71d75151d..c160280822 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java @@ -18,7 +18,7 @@ import static de.otto.edison.hal.Links.linkingTo; public abstract class SvnConfigToSvnConfigDtoMapper extends BaseMapper { @Inject - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @AfterMapping void appendLinks(SvnConfig config, @MappingTarget SvnConfigDto target) { @@ -30,12 +30,12 @@ public abstract class SvnConfigToSvnConfigDtoMapper extends BaseMapper servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java index 67f3e47950..28dbe09e92 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java @@ -53,7 +53,7 @@ public class SvnConfigResourceTest { private SvnConfigDtoToSvnConfigMapperImpl dtoToConfigMapper; @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private SvnConfigToSvnConfigDtoMapperImpl configToDtoMapper; @@ -67,7 +67,7 @@ public class SvnConfigResourceTest { when(repositoryHandler.getConfig()).thenReturn(gitConfig); SvnConfigResource gitConfigResource = new SvnConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); dispatcher.getRegistry().addSingletonResource(gitConfigResource); - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @Test diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java index cfe2c59772..5184aa3d41 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java @@ -30,7 +30,7 @@ public class SvnConfigToSvnConfigDtoMapperTest { private URI baseUri = URI.create("http://example.com/base/"); @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private UriInfoStore uriInfoStore; + private ScmPathInfoStore scmPathInfoStore; @InjectMocks private SvnConfigToSvnConfigDtoMapperImpl mapper; @@ -42,7 +42,7 @@ public class SvnConfigToSvnConfigDtoMapperTest { @Before public void init() { - when(uriInfoStore.get().getApiRestUri()).thenReturn(baseUri); + when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); expectedBaseUri = baseUri.resolve(SvnConfigResource.SVN_CONFIG_PATH_V2); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java index de0f1dd626..1683d5c11a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java @@ -1,6 +1,6 @@ package sonia.scm.api.rest; -import sonia.scm.api.v2.resources.UriInfoStore; +import sonia.scm.api.v2.resources.ScmPathInfoStore; import javax.inject.Inject; import javax.ws.rs.container.ContainerRequestContext; @@ -10,10 +10,10 @@ import javax.ws.rs.ext.Provider; @Provider public class UriInfoFilter implements ContainerRequestFilter { - private final javax.inject.Provider storeProvider; + private final javax.inject.Provider storeProvider; @Inject - public UriInfoFilter(javax.inject.Provider storeProvider) { + public UriInfoFilter(javax.inject.Provider storeProvider) { this.storeProvider = storeProvider; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MapperModule.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MapperModule.java index 9cadbfb6ff..7d8b015c27 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MapperModule.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MapperModule.java @@ -39,6 +39,6 @@ public class MapperModule extends AbstractModule { bind(UIPluginDtoMapper.class); bind(UIPluginDtoCollectionMapper.class); - bind(UriInfoStore.class).in(ServletScopes.REQUEST); + bind(ScmPathInfoStore.class).in(ServletScopes.REQUEST); } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index 74ce1a65dd..ce716f2f6f 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -31,7 +31,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Wed, 12 Sep 2018 09:19:52 +0200 Subject: [PATCH 29/48] Give name to initialization --- .../sonia/scm/api/v2/resources/ScmPathInfoStore.java | 10 +++++----- .../main/java/sonia/scm/api/rest/UriInfoFilter.java | 2 +- .../v2/resources/GroupCollectionToDtoMapperTest.java | 2 +- .../scm/api/v2/resources/ScmPathInfoStoreTest.java | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java index caa1183378..c6854e7117 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java @@ -4,17 +4,17 @@ import javax.ws.rs.core.UriInfo; public class ScmPathInfoStore { - private UriInfo uriInfo; + private ScmPathInfo pathInfo; public ScmPathInfo get() { - return () -> uriInfo.getBaseUri(); + return pathInfo; } - public void set(UriInfo uriInfo) { - if (this.uriInfo != null) { + public void setFromRestRequest(UriInfo uriInfo) { + if (this.pathInfo != null) { throw new IllegalStateException("UriInfo already set"); } - this.uriInfo = uriInfo; + this.pathInfo = uriInfo::getBaseUri; } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java index 1683d5c11a..a0b5644a05 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java @@ -19,6 +19,6 @@ public class UriInfoFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { - storeProvider.get().set(requestContext.getUriInfo()); + storeProvider.get().setFromRestRequest(requestContext.getUriInfo()); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java index b6dcf6d809..41faa49568 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java @@ -41,7 +41,7 @@ public class GroupCollectionToDtoMapperTest { @Before public void init() throws URISyntaxException { - scmPathInfoStore.set(uriInfo); + scmPathInfoStore.setFromRestRequest(uriInfo); URI baseUri = new URI("http://example.com/base/"); expectedBaseUri = baseUri.resolve(GroupRootResource.GROUPS_PATH_V2 + "/"); when(uriInfo.getBaseUri()).thenReturn(baseUri); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java index 4c3f49d2fd..1058dc182b 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java @@ -20,7 +20,7 @@ public class ScmPathInfoStoreTest { when(uriInfo.getBaseUri()).thenReturn(someUri); - scmPathInfoStore.set(uriInfo); + scmPathInfoStore.setFromRestRequest(uriInfo); assertSame(someUri, scmPathInfoStore.get().getApiRestUri()); } @@ -30,7 +30,7 @@ public class ScmPathInfoStoreTest { UriInfo uriInfo = mock(UriInfo.class); ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore(); - scmPathInfoStore.set(uriInfo); - scmPathInfoStore.set(uriInfo); + scmPathInfoStore.setFromRestRequest(uriInfo); + scmPathInfoStore.setFromRestRequest(uriInfo); } } From b809abaa45e9acee47afe0efc97ca888c1161116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 09:23:04 +0200 Subject: [PATCH 30/48] Move info initialization to filter --- .../scm/api/v2/resources/ScmPathInfoStore.java | 6 ++---- .../main/java/sonia/scm/api/rest/UriInfoFilter.java | 4 +++- .../resources/GroupCollectionToDtoMapperTest.java | 7 +++---- .../scm/api/v2/resources/ScmPathInfoStoreTest.java | 13 ++++++------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java index c6854e7117..c88bd4a2b5 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfoStore.java @@ -1,7 +1,5 @@ package sonia.scm.api.v2.resources; -import javax.ws.rs.core.UriInfo; - public class ScmPathInfoStore { private ScmPathInfo pathInfo; @@ -10,11 +8,11 @@ public class ScmPathInfoStore { return pathInfo; } - public void setFromRestRequest(UriInfo uriInfo) { + public void set(ScmPathInfo info) { if (this.pathInfo != null) { throw new IllegalStateException("UriInfo already set"); } - this.pathInfo = uriInfo::getBaseUri; + this.pathInfo = info; } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java index a0b5644a05..b602e918ea 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/UriInfoFilter.java @@ -5,6 +5,7 @@ import sonia.scm.api.v2.resources.ScmPathInfoStore; import javax.inject.Inject; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.UriInfo; import javax.ws.rs.ext.Provider; @Provider @@ -19,6 +20,7 @@ public class UriInfoFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { - storeProvider.get().setFromRestRequest(requestContext.getUriInfo()); + UriInfo uriInfo = requestContext.getUriInfo(); + storeProvider.get().set(uriInfo::getBaseUri); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java index 41faa49568..5066f56ff7 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupCollectionToDtoMapperTest.java @@ -11,7 +11,6 @@ import org.junit.Test; import sonia.scm.PageResult; import sonia.scm.group.Group; -import javax.ws.rs.core.UriInfo; import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; @@ -28,7 +27,7 @@ import static sonia.scm.PageResult.createPage; public class GroupCollectionToDtoMapperTest { - private final UriInfo uriInfo = mock(UriInfo.class); + private final ScmPathInfo uriInfo = mock(ScmPathInfo.class); private final ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore(); private final ResourceLinks resourceLinks = new ResourceLinks(scmPathInfoStore); private final GroupToGroupDtoMapper groupToDtoMapper = mock(GroupToGroupDtoMapper.class); @@ -41,10 +40,10 @@ public class GroupCollectionToDtoMapperTest { @Before public void init() throws URISyntaxException { - scmPathInfoStore.setFromRestRequest(uriInfo); + scmPathInfoStore.set(uriInfo); URI baseUri = new URI("http://example.com/base/"); expectedBaseUri = baseUri.resolve(GroupRootResource.GROUPS_PATH_V2 + "/"); - when(uriInfo.getBaseUri()).thenReturn(baseUri); + when(uriInfo.getApiRestUri()).thenReturn(baseUri); subjectThreadState.bind(); ThreadContext.bind(subject); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java index 1058dc182b..544a918b8b 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ScmPathInfoStoreTest.java @@ -2,7 +2,6 @@ package sonia.scm.api.v2.resources; import org.junit.Test; -import javax.ws.rs.core.UriInfo; import java.net.URI; import static org.junit.Assert.assertSame; @@ -15,22 +14,22 @@ public class ScmPathInfoStoreTest { public void shouldReturnSetInfo() { URI someUri = URI.create("/anything"); - UriInfo uriInfo = mock(UriInfo.class); + ScmPathInfo uriInfo = mock(ScmPathInfo.class); ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore(); - when(uriInfo.getBaseUri()).thenReturn(someUri); + when(uriInfo.getApiRestUri()).thenReturn(someUri); - scmPathInfoStore.setFromRestRequest(uriInfo); + scmPathInfoStore.set(uriInfo); assertSame(someUri, scmPathInfoStore.get().getApiRestUri()); } @Test(expected = IllegalStateException.class) public void shouldFailIfSetTwice() { - UriInfo uriInfo = mock(UriInfo.class); + ScmPathInfo uriInfo = mock(ScmPathInfo.class); ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore(); - scmPathInfoStore.setFromRestRequest(uriInfo); - scmPathInfoStore.setFromRestRequest(uriInfo); + scmPathInfoStore.set(uriInfo); + scmPathInfoStore.set(uriInfo); } } From ef28350ce31279d9442e3e605b6b85d3d35c7ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 11:43:29 +0200 Subject: [PATCH 31/48] Handle missing request scope for url computation --- .../InitializingHttpScmProtocolWrapper.java | 29 +++- .../test/java/sonia/scm}/MockProvider.java | 6 +- ...nitializingHttpScmProtocolWrapperTest.java | 143 ++++++++++++++++++ scm-webapp/pom.xml | 9 +- .../v2/resources/BranchRootResourceTest.java | 1 + .../resources/ChangesetRootResourceTest.java | 1 + .../v2/resources/GroupRootResourceTest.java | 1 + .../resources/PermissionRootResourceTest.java | 1 + .../resources/RepositoryRootResourceTest.java | 1 + .../RepositoryTypeRootResourceTest.java | 7 +- .../v2/resources/SourceRootResourceTest.java | 2 +- .../api/v2/resources/TagRootResourceTest.java | 1 + .../v2/resources/UserRootResourceTest.java | 1 + 13 files changed, 192 insertions(+), 11 deletions(-) rename {scm-webapp/src/test/java/sonia/scm/api/v2/resources => scm-core/src/test/java/sonia/scm}/MockProvider.java (80%) create mode 100644 scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 450f1d4495..7e7fb243cc 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -1,5 +1,7 @@ package sonia.scm.repository.spi; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; @@ -11,9 +13,15 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Optional; + +import static java.util.Optional.empty; +import static java.util.Optional.of; public abstract class InitializingHttpScmProtocolWrapper { + private static final Logger logger = LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); + private final Provider delegateProvider; private final Provider permissionFilterProvider; private final Provider uriInfoStore; @@ -38,11 +46,24 @@ public abstract class InitializingHttpScmProtocolWrapper { } private String computeBasePath() { - if (uriInfoStore.get() != null && uriInfoStore.get().get() != null) { - return uriInfoStore.get().get().getApiRestUri().resolve("../..").toASCIIString(); - } else { - return scmConfiguration.getBaseUrl(); + return getPathFromScmPathInfoIfAvailable().orElse(getPathFromConfiguration()); + } + + private Optional getPathFromScmPathInfoIfAvailable() { + try { + ScmPathInfoStore scmPathInfoStore = uriInfoStore.get(); + if (scmPathInfoStore != null && scmPathInfoStore.get() != null) { + return of(scmPathInfoStore.get().getApiRestUri().resolve("../..").toASCIIString()); + } + } catch (Exception e) { + logger.debug("could not get ScmPathInfoStore from context", e); } + return empty(); + } + + private String getPathFromConfiguration() { + logger.debug("using base path from configuration: " + scmConfiguration.getBaseUrl()); + return scmConfiguration.getBaseUrl(); } private class ProtocolWrapper extends HttpScmProtocol { diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MockProvider.java b/scm-core/src/test/java/sonia/scm/MockProvider.java similarity index 80% rename from scm-webapp/src/test/java/sonia/scm/api/v2/resources/MockProvider.java rename to scm-core/src/test/java/sonia/scm/MockProvider.java index bf84e4fe15..fae1b07586 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MockProvider.java +++ b/scm-core/src/test/java/sonia/scm/MockProvider.java @@ -1,4 +1,4 @@ -package sonia.scm.api.v2.resources; +package sonia.scm; import javax.inject.Provider; @@ -8,11 +8,11 @@ import static org.mockito.Mockito.when; /** * A mockito implementation of CDI {@link javax.inject.Provider}. */ -class MockProvider { +public class MockProvider { private MockProvider() {} - static Provider of(I instance) { + public static Provider of(I instance) { @SuppressWarnings("unchecked") // Can't make mockito return typed provider Provider provider = mock(Provider.class); when(provider.get()).thenReturn(instance); diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java new file mode 100644 index 0000000000..3b43e16e5b --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java @@ -0,0 +1,143 @@ +package sonia.scm.repository.spi; + +import com.google.inject.ProvisionException; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.stubbing.Answer; +import org.mockito.stubbing.OngoingStubbing; +import sonia.scm.MockProvider; +import sonia.scm.api.v2.resources.ScmPathInfo; +import sonia.scm.api.v2.resources.ScmPathInfoStore; +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.Repository; +import sonia.scm.web.filter.PermissionFilter; + +import javax.inject.Provider; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +public class InitializingHttpScmProtocolWrapperTest { + + private static final Repository REPOSITORY = new Repository("", "git", "space", "name"); + + @Mock + private ScmProviderHttpServlet delegateServlet; + @Mock + private PermissionFilter permissionFilter; + @Mock + private ScmPathInfoStore pathInfoStore; + @Mock + private ScmConfiguration scmConfiguration; + private Provider pathInfoStoreProvider; + + @Mock + private HttpServletRequest request; + @Mock + private HttpServletResponse response; + @Mock + private ServletConfig servletConfig; + + private InitializingHttpScmProtocolWrapper wrapper; + + @Before + public void init() { + initMocks(this); + pathInfoStoreProvider = MockProvider.of(pathInfoStore); + wrapper = new InitializingHttpScmProtocolWrapper(MockProvider.of(this.delegateServlet), MockProvider.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) {}; + when(scmConfiguration.getBaseUrl()).thenReturn("http://example.com/scm"); + } + + @Test + public void shouldUsePathFromPathInfo() { + mockSetPathInfo(); + + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + assertEquals("http://example.com/scm/repo/space/name", httpScmProtocol.getUrl()); + } + + @Test + public void shouldUseConfigurationWhenPathInfoNotSet() { + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + assertEquals("http://example.com/scm/repo/space/name", httpScmProtocol.getUrl()); + } + + @Test + public void shouldUseConfigurationWhenNotInRequestScope() { + when(pathInfoStoreProvider.get()).thenThrow(new ProvisionException("test")); + + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + assertEquals("http://example.com/scm/repo/space/name", httpScmProtocol.getUrl()); + } + + @Test + public void shouldInitializeAndDelegateRequestThroughFilter() throws ServletException, IOException { + doAnswer(proceedInvocation()). + when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + httpScmProtocol.serve(request, response, servletConfig); + + verify(delegateServlet).init(servletConfig); + verify(delegateServlet).service(request, response, REPOSITORY); + } + + @Test + public void shouldNotDelegateRequestWhenFilterBlocks() throws ServletException, IOException { + doNothing(). + when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + httpScmProtocol.serve(request, response, servletConfig); + + verify(delegateServlet, never()).service(request, response, REPOSITORY); + } + + @Test + public void shouldInitializeOnlyOnce() throws ServletException, IOException { + doAnswer(proceedInvocation()). + when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); + HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); + + httpScmProtocol.serve(request, response, servletConfig); + httpScmProtocol.serve(request, response, servletConfig); + + verify(delegateServlet, times(1)).init(servletConfig); + verify(delegateServlet, times(2)).service(request, response, REPOSITORY); + } + + private Answer proceedInvocation() { + return invocation -> { + ((PermissionFilter.ContinuationServlet) invocation.getArgument(3)).doService(); + return null; + }; + } + + private OngoingStubbing mockSetPathInfo() { + return when(pathInfoStore.get()).thenReturn(new ScmPathInfo() { + @Override + public URI getApiRestUri() { + return URI.create("http://example.com/scm/api/rest/"); + } + }); + } + +} diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index fb5cc57e44..c7d4dbc45c 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -49,7 +49,14 @@ scm-core 2.0.0-SNAPSHOT - + + sonia.scm + scm-core + 2.0.0-SNAPSHOT + tests + test + + sonia.scm scm-dao-xml diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java index e23d3dc39b..f2563b3522 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java @@ -17,6 +17,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.MockProvider; import sonia.scm.repository.Branch; import sonia.scm.repository.Branches; import sonia.scm.repository.Changeset; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java index 40aa61852a..45ff631828 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java @@ -18,6 +18,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.MockProvider; import sonia.scm.api.rest.AuthorizationExceptionMapper; import sonia.scm.repository.Changeset; import sonia.scm.repository.ChangesetPagingResult; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java index 1e42016ace..9b1699691c 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java @@ -12,6 +12,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.api.rest.JSONContextResolver; import sonia.scm.api.rest.ObjectMapperProvider; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java index 8d05c1f455..f4c88b7be1 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.mockito.InjectMocks; import org.mockito.Mock; +import sonia.scm.MockProvider; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Permission; import sonia.scm.repository.PermissionType; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index ca679764ad..68ea56299b 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -12,6 +12,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Permission; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java index 9adca13225..a0bb5ccf08 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java @@ -12,6 +12,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.MockProvider; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryType; import sonia.scm.web.VndMediaType; @@ -22,8 +23,10 @@ import java.util.List; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_OK; -import static org.junit.Assert.*; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalToIgnoringCase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.Silent.class) diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java index a59ed0c103..4bc11fad82 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java @@ -1,7 +1,6 @@ package sonia.scm.api.v2.resources; import org.jboss.resteasy.core.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -10,6 +9,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.MockProvider; import sonia.scm.repository.BrowserResult; import sonia.scm.repository.FileObject; import sonia.scm.repository.NamespaceAndName; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java index 92d11b3895..eaa7deb578 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java @@ -17,6 +17,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.MockProvider; import sonia.scm.api.rest.AuthorizationExceptionMapper; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java index 5004eb7665..e54c875373 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java @@ -13,6 +13,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.user.User; import sonia.scm.user.UserManager; From f5d5d3a6dc680749744281d0a48a181524bd56fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 11:47:53 +0200 Subject: [PATCH 32/48] Move path computation away from protocol handling --- .../src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java | 4 ++++ .../repository/spi/InitializingHttpScmProtocolWrapper.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java index 0afb379eed..34fa5004fc 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java @@ -4,4 +4,8 @@ import java.net.URI; public interface ScmPathInfo { URI getApiRestUri(); + + default URI getRootUri() { + return getApiRestUri().resolve("../.."); + } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 7e7fb243cc..c5fd037cc8 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -53,7 +53,7 @@ public abstract class InitializingHttpScmProtocolWrapper { try { ScmPathInfoStore scmPathInfoStore = uriInfoStore.get(); if (scmPathInfoStore != null && scmPathInfoStore.get() != null) { - return of(scmPathInfoStore.get().getApiRestUri().resolve("../..").toASCIIString()); + return of(scmPathInfoStore.get().getRootUri().toASCIIString()); } } catch (Exception e) { logger.debug("could not get ScmPathInfoStore from context", e); From f47c5ef16f5cc22ddeb901c443725c379d2041f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 12:05:24 +0200 Subject: [PATCH 33/48] Replace MockProvider test helper with guice class --- .../src/test/java/sonia/scm/MockProvider.java | 22 ------------------- ...nitializingHttpScmProtocolWrapperTest.java | 9 +++++--- scm-webapp/pom.xml | 7 ------ .../v2/resources/BranchRootResourceTest.java | 4 ++-- .../resources/ChangesetRootResourceTest.java | 6 ++--- .../v2/resources/GroupRootResourceTest.java | 4 ++-- .../resources/PermissionRootResourceTest.java | 6 ++--- .../resources/RepositoryRootResourceTest.java | 4 ++-- .../RepositoryTypeRootResourceTest.java | 4 ++-- .../v2/resources/SourceRootResourceTest.java | 6 ++--- .../api/v2/resources/TagRootResourceTest.java | 6 ++--- .../v2/resources/UserRootResourceTest.java | 6 ++--- 12 files changed, 29 insertions(+), 55 deletions(-) delete mode 100644 scm-core/src/test/java/sonia/scm/MockProvider.java diff --git a/scm-core/src/test/java/sonia/scm/MockProvider.java b/scm-core/src/test/java/sonia/scm/MockProvider.java deleted file mode 100644 index fae1b07586..0000000000 --- a/scm-core/src/test/java/sonia/scm/MockProvider.java +++ /dev/null @@ -1,22 +0,0 @@ -package sonia.scm; - -import javax.inject.Provider; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * A mockito implementation of CDI {@link javax.inject.Provider}. - */ -public class MockProvider { - - private MockProvider() {} - - public static Provider of(I instance) { - @SuppressWarnings("unchecked") // Can't make mockito return typed provider - Provider provider = mock(Provider.class); - when(provider.get()).thenReturn(instance); - return provider; - } - -} diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java index 3b43e16e5b..1e742a768a 100644 --- a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java @@ -1,12 +1,12 @@ package sonia.scm.repository.spi; import com.google.inject.ProvisionException; +import com.google.inject.util.Providers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.stubbing.Answer; import org.mockito.stubbing.OngoingStubbing; -import sonia.scm.MockProvider; import sonia.scm.api.v2.resources.ScmPathInfo; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -58,8 +59,10 @@ public class InitializingHttpScmProtocolWrapperTest { @Before public void init() { initMocks(this); - pathInfoStoreProvider = MockProvider.of(pathInfoStore); - wrapper = new InitializingHttpScmProtocolWrapper(MockProvider.of(this.delegateServlet), MockProvider.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) {}; + pathInfoStoreProvider = mock(Provider.class); + when(pathInfoStoreProvider.get()).thenReturn(pathInfoStore); + + wrapper = new InitializingHttpScmProtocolWrapper(Providers.of(this.delegateServlet), Providers.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) {}; when(scmConfiguration.getBaseUrl()).thenReturn("http://example.com/scm"); } diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index c7d4dbc45c..bc40e434cf 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -49,13 +49,6 @@ scm-core 2.0.0-SNAPSHOT - - sonia.scm - scm-core - 2.0.0-SNAPSHOT - tests - test - sonia.scm diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java index f2563b3522..bc883ef37a 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java @@ -1,5 +1,6 @@ package sonia.scm.api.v2.resources; +import com.google.inject.util.Providers; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.SubjectThreadState; @@ -17,7 +18,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.MockProvider; import sonia.scm.repository.Branch; import sonia.scm.repository.Branches; import sonia.scm.repository.Changeset; @@ -93,7 +93,7 @@ public class BranchRootResourceTest { changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); BranchCollectionToDtoMapper branchCollectionToDtoMapper = new BranchCollectionToDtoMapper(branchToDtoMapper, resourceLinks); branchRootResource = new BranchRootResource(serviceFactory, branchToDtoMapper, branchCollectionToDtoMapper, changesetCollectionToDtoMapper); - RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider.of(new RepositoryResource(null, null, null, null, MockProvider.of(branchRootResource), null, null, null, null, null)), null); + RepositoryRootResource repositoryRootResource = new RepositoryRootResource(Providers.of(new RepositoryResource(null, null, null, null, Providers.of(branchRootResource), null, null, null, null, null)), null); dispatcher.getRegistry().addSingletonResource(repositoryRootResource); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java index 45ff631828..3980dcef1f 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java @@ -1,6 +1,7 @@ package sonia.scm.api.v2.resources; +import com.google.inject.util.Providers; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.SubjectThreadState; @@ -18,7 +19,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.MockProvider; import sonia.scm.api.rest.AuthorizationExceptionMapper; import sonia.scm.repository.Changeset; import sonia.scm.repository.ChangesetPagingResult; @@ -80,9 +80,9 @@ public class ChangesetRootResourceTest { public void prepareEnvironment() throws Exception { changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); changesetRootResource = new ChangesetRootResource(serviceFactory, changesetCollectionToDtoMapper, changesetToChangesetDtoMapper); - RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider + RepositoryRootResource repositoryRootResource = new RepositoryRootResource(Providers .of(new RepositoryResource(null, null, null, null, null, - MockProvider.of(changesetRootResource), null, null, null, null)), null); + Providers.of(changesetRootResource), null, null, null, null)), null); dispatcher.getRegistry().addSingletonResource(repositoryRootResource); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java index 9b1699691c..f662542ff7 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java @@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; +import com.google.inject.util.Providers; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; @@ -12,7 +13,6 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; -import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.api.rest.JSONContextResolver; import sonia.scm.api.rest.ObjectMapperProvider; @@ -74,7 +74,7 @@ public class GroupRootResourceTest { GroupCollectionToDtoMapper groupCollectionToDtoMapper = new GroupCollectionToDtoMapper(groupToDtoMapper, resourceLinks); GroupCollectionResource groupCollectionResource = new GroupCollectionResource(groupManager, dtoToGroupMapper, groupCollectionToDtoMapper, resourceLinks); GroupResource groupResource = new GroupResource(groupManager, groupToDtoMapper, dtoToGroupMapper); - GroupRootResource groupRootResource = new GroupRootResource(MockProvider.of(groupCollectionResource), MockProvider.of(groupResource)); + GroupRootResource groupRootResource = new GroupRootResource(Providers.of(groupCollectionResource), Providers.of(groupResource)); dispatcher = createDispatcher(groupRootResource); dispatcher.getProviderFactory().registerProviderInstance(new JSONContextResolver(new ObjectMapperProvider().get())); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java index f4c88b7be1..25f59c3e38 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PermissionRootResourceTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.collect.ImmutableList; +import com.google.inject.util.Providers; import de.otto.edison.hal.HalRepresentation; import lombok.ToString; import lombok.extern.slf4j.Slf4j; @@ -27,7 +28,6 @@ import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.mockito.InjectMocks; import org.mockito.Mock; -import sonia.scm.MockProvider; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Permission; import sonia.scm.repository.PermissionType; @@ -138,8 +138,8 @@ public class PermissionRootResourceTest { initMocks(this); permissionCollectionToDtoMapper = new PermissionCollectionToDtoMapper(permissionToPermissionDtoMapper, resourceLinks); permissionRootResource = new PermissionRootResource(permissionDtoToPermissionMapper, permissionToPermissionDtoMapper, permissionCollectionToDtoMapper, resourceLinks, repositoryManager); - RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider - .of(new RepositoryResource(null, null, null, null, null, null, null, null, MockProvider.of(permissionRootResource), null)), null); + RepositoryRootResource repositoryRootResource = new RepositoryRootResource(Providers + .of(new RepositoryResource(null, null, null, null, null, null, null, null, Providers.of(permissionRootResource), null)), null); dispatcher = createDispatcher(repositoryRootResource); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index 68ea56299b..3b76d42f44 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; +import com.google.inject.util.Providers; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; @@ -12,7 +13,6 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; -import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Permission; @@ -90,7 +90,7 @@ public class RepositoryRootResourceTest { RepositoryResource repositoryResource = new RepositoryResource(repositoryToDtoMapper, dtoToRepositoryMapper, repositoryManager, null, null, null, null, null, null, null); RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks); RepositoryCollectionResource repositoryCollectionResource = new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks); - RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider.of(repositoryResource), MockProvider.of(repositoryCollectionResource)); + RepositoryRootResource repositoryRootResource = new RepositoryRootResource(Providers.of(repositoryResource), Providers.of(repositoryCollectionResource)); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(scmPathInfoStore.get()).thenReturn(uriInfo); when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java index a0bb5ccf08..2476785d70 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java @@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.google.inject.util.Providers; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; @@ -12,7 +13,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.MockProvider; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryType; import sonia.scm.web.VndMediaType; @@ -55,7 +55,7 @@ public class RepositoryTypeRootResourceTest { RepositoryTypeCollectionToDtoMapper collectionMapper = new RepositoryTypeCollectionToDtoMapper(mapper, resourceLinks); RepositoryTypeCollectionResource collectionResource = new RepositoryTypeCollectionResource(repositoryManager, collectionMapper); RepositoryTypeResource resource = new RepositoryTypeResource(repositoryManager, mapper); - RepositoryTypeRootResource rootResource = new RepositoryTypeRootResource(MockProvider.of(collectionResource), MockProvider.of(resource)); + RepositoryTypeRootResource rootResource = new RepositoryTypeRootResource(Providers.of(collectionResource), Providers.of(resource)); dispatcher.getRegistry().addSingletonResource(rootResource); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java index 4bc11fad82..69b4af9871 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java @@ -1,5 +1,6 @@ package sonia.scm.api.v2.resources; +import com.google.inject.util.Providers; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; @@ -9,7 +10,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.MockProvider; import sonia.scm.repository.BrowserResult; import sonia.scm.repository.FileObject; import sonia.scm.repository.NamespaceAndName; @@ -65,13 +65,13 @@ public class SourceRootResourceTest { when(fileObjectToFileObjectDtoMapper.map(any(FileObject.class), any(NamespaceAndName.class), anyString())).thenReturn(dto); SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToBrowserResultDtoMapper); RepositoryRootResource repositoryRootResource = - new RepositoryRootResource(MockProvider.of(new RepositoryResource(null, + new RepositoryRootResource(Providers.of(new RepositoryResource(null, null, null, null, null, null, - MockProvider.of(sourceRootResource), + Providers.of(sourceRootResource), null, null, null)), diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java index eaa7deb578..0266d9a9e0 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java @@ -1,5 +1,6 @@ package sonia.scm.api.v2.resources; +import com.google.inject.util.Providers; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.SubjectThreadState; @@ -17,7 +18,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.MockProvider; import sonia.scm.api.rest.AuthorizationExceptionMapper; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; @@ -73,8 +73,8 @@ public class TagRootResourceTest { public void prepareEnvironment() throws Exception { tagCollectionToDtoMapper = new TagCollectionToDtoMapper(resourceLinks, tagToTagDtoMapper); tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper); - RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider - .of(new RepositoryResource(null, null, null, MockProvider.of(tagRootResource), null, + RepositoryRootResource repositoryRootResource = new RepositoryRootResource(Providers + .of(new RepositoryResource(null, null, null, Providers.of(tagRootResource), null, null, null, null, null, null)), null); dispatcher.getRegistry().addSingletonResource(repositoryRootResource); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java index e54c875373..c0b50bfd5e 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java @@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; +import com.google.inject.util.Providers; import org.apache.shiro.authc.credential.PasswordService; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; @@ -13,7 +14,6 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; -import sonia.scm.MockProvider; import sonia.scm.PageResult; import sonia.scm.user.User; import sonia.scm.user.UserManager; @@ -74,8 +74,8 @@ public class UserRootResourceTest { UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper, userCollectionToDtoMapper, resourceLinks); UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager); - UserRootResource userRootResource = new UserRootResource(MockProvider.of(userCollectionResource), - MockProvider.of(userResource)); + UserRootResource userRootResource = new UserRootResource(Providers.of(userCollectionResource), + Providers.of(userResource)); dispatcher = createDispatcher(userRootResource); } From 9aa9b779222c592994aa8c946c078feb6e8d4914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 12 Sep 2018 12:24:57 +0200 Subject: [PATCH 34/48] Use constant for rest api path --- .../sonia/scm/api/v2/resources/ScmPathInfo.java | 3 +++ .../src/main/java/sonia/scm/filter/Filters.java | 12 +++++++----- .../src/main/java/sonia/scm/ScmServletModule.java | 8 +++++--- .../main/java/sonia/scm/filter/SecurityFilter.java | 14 +++++++------- .../java/sonia/scm/security/SecurityRequests.java | 4 +++- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java index 34fa5004fc..fa975520c1 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/ScmPathInfo.java @@ -3,6 +3,9 @@ package sonia.scm.api.v2.resources; import java.net.URI; public interface ScmPathInfo { + + String REST_API_PATH = "/api/rest"; + URI getApiRestUri(); default URI getRootUri() { diff --git a/scm-core/src/main/java/sonia/scm/filter/Filters.java b/scm-core/src/main/java/sonia/scm/filter/Filters.java index b6a45811bc..b1f5ea47cf 100644 --- a/scm-core/src/main/java/sonia/scm/filter/Filters.java +++ b/scm-core/src/main/java/sonia/scm/filter/Filters.java @@ -31,6 +31,8 @@ package sonia.scm.filter; +import static sonia.scm.api.v2.resources.ScmPathInfo.REST_API_PATH; + /** * Useful constants for filter implementations. * @@ -44,26 +46,26 @@ public final class Filters public static final String PATTERN_ALL = "/*"; /** Field description */ - public static final String PATTERN_CONFIG = "/api/rest/config*"; + public static final String PATTERN_CONFIG = REST_API_PATH + "/config*"; /** Field description */ public static final String PATTERN_DEBUG = "/debug.html"; /** Field description */ - public static final String PATTERN_GROUPS = "/api/rest/groups*"; + public static final String PATTERN_GROUPS = REST_API_PATH + "/groups*"; /** Field description */ - public static final String PATTERN_PLUGINS = "/api/rest/plugins*"; + public static final String PATTERN_PLUGINS = REST_API_PATH + "/plugins*"; /** Field description */ public static final String PATTERN_RESOURCE_REGEX = "^/(?:resources|api|plugins|index)[\\./].*(?:html|\\.css|\\.js|\\.xml|\\.json|\\.txt)"; /** Field description */ - public static final String PATTERN_RESTAPI = "/api/rest/*"; + public static final String PATTERN_RESTAPI = REST_API_PATH + "/*"; /** Field description */ - public static final String PATTERN_USERS = "/api/rest/users*"; + public static final String PATTERN_USERS = REST_API_PATH + "/users*"; /** authentication priority */ public static final int PRIORITY_AUTHENTICATION = 5000; diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index fd330a6d1d..e9ec9e4a39 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -119,6 +119,8 @@ import sonia.scm.web.security.DefaultAdministrationContext; import javax.net.ssl.SSLContext; import javax.servlet.ServletContext; +import static sonia.scm.api.v2.resources.ScmPathInfo.REST_API_PATH; + /** * * @author Sebastian Sdorra @@ -128,14 +130,14 @@ public class ScmServletModule extends ServletModule /** Field description */ public static final String[] PATTERN_ADMIN = new String[] { - "/api/rest/groups*", - "/api/rest/users*", "/api/rest/plguins*" }; + REST_API_PATH + "/groups*", + REST_API_PATH + "/users*", REST_API_PATH + "/plguins*" }; /** Field description */ public static final String PATTERN_ALL = "/*"; /** Field description */ - public static final String PATTERN_CONFIG = "/api/rest/config*"; + public static final String PATTERN_CONFIG = REST_API_PATH + "/config*"; /** Field description */ public static final String PATTERN_DEBUG = "/debug.html"; diff --git a/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java b/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java index 0d59d77027..de0d689c52 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/SecurityFilter.java @@ -37,10 +37,8 @@ package sonia.scm.filter; import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; - import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; - import sonia.scm.Priority; import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; @@ -48,14 +46,15 @@ import sonia.scm.security.SecurityRequests; import sonia.scm.web.filter.HttpFilter; import sonia.scm.web.filter.SecurityHttpServletRequestWrapper; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static sonia.scm.api.v2.resources.ScmPathInfo.REST_API_PATH; + +//~--- JDK imports ------------------------------------------------------------ /** * @@ -63,7 +62,8 @@ import javax.servlet.http.HttpServletResponse; */ @Priority(Filters.PRIORITY_AUTHORIZATION) // TODO find a better way for unprotected resources -@WebElement(value = "/api/rest/(?!v2/ui).*", regex = true) +@WebElement(value = REST_API_PATH + "" + + "/(?!v2/ui).*", regex = true) public class SecurityFilter extends HttpFilter { diff --git a/scm-webapp/src/main/java/sonia/scm/security/SecurityRequests.java b/scm-webapp/src/main/java/sonia/scm/security/SecurityRequests.java index 225767cd3b..81bb2092c9 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/SecurityRequests.java +++ b/scm-webapp/src/main/java/sonia/scm/security/SecurityRequests.java @@ -3,12 +3,14 @@ package sonia.scm.security; import javax.servlet.http.HttpServletRequest; import java.util.regex.Pattern; +import static sonia.scm.api.v2.resources.ScmPathInfo.REST_API_PATH; + /** * Created by masuewer on 04.07.18. */ public final class SecurityRequests { - private static final Pattern URI_LOGIN_PATTERN = Pattern.compile("/api/rest(?:/v2)?/auth/access_token"); + private static final Pattern URI_LOGIN_PATTERN = Pattern.compile(REST_API_PATH + "(?:/v2)?/auth/access_token"); private SecurityRequests() {} From 145502a7b8dd1a21d3f0855227ff89d1f0d70f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 13 Sep 2018 10:35:10 +0200 Subject: [PATCH 35/48] Introduce extension point for further protocol implementations --- .../scm/repository/api/RepositoryService.java | 44 +++++++++--------- .../api/RepositoryServiceFactory.java | 8 +++- .../repository/api/ScmProtocolProvider.java | 12 +++++ .../InitializingHttpScmProtocolWrapper.java | 7 ++- .../spi/RepositoryServiceProvider.java | 3 -- .../repository/api/RepositoryServiceTest.java | 43 +++++++++++++----- ...nitializingHttpScmProtocolWrapperTest.java | 19 +++++--- .../spi/GitRepositoryServiceProvider.java | 14 +----- .../spi/GitRepositoryServiceResolver.java | 11 ++--- .../web/GitScmProtocolProviderWrapper.java | 7 +++ .../spi/HgRepositoryServiceProvider.java | 12 +---- .../spi/HgRepositoryServiceResolver.java | 45 +++---------------- .../scm/web/HgScmProtocolProviderWrapper.java | 7 +++ .../spi/SvnRepositoryServiceProvider.java | 19 +------- .../spi/SvnRepositoryServiceResolver.java | 12 ++--- .../web/SvnScmProtocolProviderWrapper.java | 7 +++ .../RepositoryToRepositoryDtoMapper.java | 5 +-- .../resources/RepositoryRootResourceTest.java | 4 +- .../RepositoryToRepositoryDtoMapperTest.java | 11 +++-- 19 files changed, 137 insertions(+), 153 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java index 61c3ce5d87..4d388609d8 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java @@ -42,7 +42,8 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import java.io.Closeable; import java.io.IOException; -import java.util.Collection; +import java.util.Set; +import java.util.stream.Stream; /** * From the {@link RepositoryService} it is possible to access all commands for @@ -80,29 +81,30 @@ import java.util.Collection; * @since 1.17 */ public final class RepositoryService implements Closeable { - private CacheManager cacheManager; - private PreProcessorUtil preProcessorUtil; - private RepositoryServiceProvider provider; - private Repository repository; - private static final Logger logger = - LoggerFactory.getLogger(RepositoryService.class); + + private static final Logger logger = LoggerFactory.getLogger(RepositoryService.class); + + private final CacheManager cacheManager; + private final PreProcessorUtil preProcessorUtil; + private final RepositoryServiceProvider provider; + private final Repository repository; + private final Set protocolProviders; /** * Constructs a new {@link RepositoryService}. This constructor should only * be called from the {@link RepositoryServiceFactory}. - * - * @param cacheManager cache manager + * @param cacheManager cache manager * @param provider implementation for {@link RepositoryServiceProvider} * @param repository the repository - * @param preProcessorUtil */ RepositoryService(CacheManager cacheManager, - RepositoryServiceProvider provider, Repository repository, - PreProcessorUtil preProcessorUtil) { + RepositoryServiceProvider provider, Repository repository, + PreProcessorUtil preProcessorUtil, Set protocolProviders) { this.cacheManager = cacheManager; this.provider = provider; this.repository = repository; this.preProcessorUtil = preProcessorUtil; + this.protocolProviders = protocolProviders; } /** @@ -359,16 +361,18 @@ public final class RepositoryService implements Closeable { } - public Collection getSupportedProtocols() { - return provider.getSupportedProtocols(); + public Stream getSupportedProtocols() { + return protocolProviders.stream().filter(provider -> provider.getType().equals(getRepository().getType())).map(this::createProviderInstanceForRepository); + } + + private ScmProtocol createProviderInstanceForRepository(ScmProtocolProvider protocolProvider) { + return protocolProvider.get(repository); } public T getProtocol(Class clazz) { - for (ScmProtocol scmProtocol : getSupportedProtocols()) { - if (clazz.isAssignableFrom(scmProtocol.getClass())) { - return (T) scmProtocol; - } - } - throw new IllegalArgumentException("no implementation for " + clazz.getName() + " and repository type " + getRepository().getType()); + return (T) getSupportedProtocols() + .filter(scmProtocol -> clazz.isAssignableFrom(scmProtocol.getClass())) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("no implementation for " + clazz.getName() + " and repository type " + getRepository().getType())); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java index 33f57d4524..fbb1ee6b58 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java @@ -137,13 +137,15 @@ public final class RepositoryServiceFactory @Inject public RepositoryServiceFactory(ScmConfiguration configuration, CacheManager cacheManager, RepositoryManager repositoryManager, - Set resolvers, PreProcessorUtil preProcessorUtil) + Set resolvers, PreProcessorUtil preProcessorUtil, + Set protocolProviders) { this.configuration = configuration; this.cacheManager = cacheManager; this.repositoryManager = repositoryManager; this.resolvers = resolvers; this.preProcessorUtil = preProcessorUtil; + this.protocolProviders = protocolProviders; ScmEventBus.getInstance().register(new CacheClearHook(cacheManager)); } @@ -252,7 +254,7 @@ public final class RepositoryServiceFactory } service = new RepositoryService(cacheManager, provider, repository, - preProcessorUtil); + preProcessorUtil, protocolProviders); break; } @@ -367,4 +369,6 @@ public final class RepositoryServiceFactory /** service resolvers */ private final Set resolvers; + + private Set protocolProviders; } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java new file mode 100644 index 0000000000..d4be5dca59 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java @@ -0,0 +1,12 @@ +package sonia.scm.repository.api; + +import sonia.scm.plugin.ExtensionPoint; +import sonia.scm.repository.Repository; + +@ExtensionPoint(multi = true) +public interface ScmProtocolProvider { + + String getType(); + + ScmProtocol get(Repository repository); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index c5fd037cc8..6e59470c5e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; +import sonia.scm.repository.api.ScmProtocolProvider; import sonia.scm.web.filter.PermissionFilter; import javax.inject.Provider; @@ -18,7 +19,7 @@ import java.util.Optional; import static java.util.Optional.empty; import static java.util.Optional.of; -public abstract class InitializingHttpScmProtocolWrapper { +public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolProvider { private static final Logger logger = LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); @@ -41,7 +42,11 @@ public abstract class InitializingHttpScmProtocolWrapper { httpServlet.init(config); } + @Override public HttpScmProtocol get(Repository repository) { + if (!repository.getType().equals(getType())) { + throw new IllegalArgumentException("cannot handle repository with type " + repository.getType() + " with protocol for type " + getType()); + } return new ProtocolWrapper(repository); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java index 0a56800f82..e0981b840c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java @@ -36,7 +36,6 @@ package sonia.scm.repository.spi; import sonia.scm.repository.Feature; import sonia.scm.repository.api.Command; import sonia.scm.repository.api.CommandNotSupportedException; -import sonia.scm.repository.api.ScmProtocol; import java.io.Closeable; import java.io.IOException; @@ -240,6 +239,4 @@ public abstract class RepositoryServiceProvider implements Closeable { throw new CommandNotSupportedException(Command.UNBUNDLE); } - - public abstract Set getSupportedProtocols(); } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java index 9cb398b571..2ceafc19bb 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/RepositoryServiceTest.java @@ -8,38 +8,43 @@ import sonia.scm.repository.spi.RepositoryServiceProvider; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.util.Collection; import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.util.IterableUtil.sizeOf; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class RepositoryServiceTest { private final RepositoryServiceProvider provider = mock(RepositoryServiceProvider.class); - private final Repository repository = mock(Repository.class); + private final Repository repository = new Repository("", "git", "space", "repo"); @Test - public void shouldReturnProtocolsFromProvider() { - when(provider.getSupportedProtocols()).thenReturn(Collections.singleton(new DummyHttpProtocol(repository))); + public void shouldReturnMatchingProtocolsFromProvider() { + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider())); + Stream supportedProtocols = repositoryService.getSupportedProtocols(); - RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); - Collection supportedProtocols = repositoryService.getSupportedProtocols(); + assertThat(sizeOf(supportedProtocols.collect(Collectors.toList()))).isEqualTo(1); + } - assertThat(sizeOf(supportedProtocols)).isEqualTo(1); + @Test + public void shouldFindKnownProtocol() { + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider())); + + HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class); + + assertThat(protocol).isNotNull(); } @Test public void shouldFailForUnknownProtocol() { - when(provider.getSupportedProtocols()).thenReturn(Collections.emptySet()); - - RepositoryService repositoryService = new RepositoryService(null, provider, repository, null); + RepositoryService repositoryService = new RepositoryService(null, provider, repository, null, Collections.singleton(new DummyScmProtocolProvider())); assertThrows(IllegalArgumentException.class, () -> { - repositoryService.getProtocol(HttpScmProtocol.class); + repositoryService.getProtocol(UnknownScmProtocol.class); }); } @@ -52,4 +57,18 @@ public class RepositoryServiceTest { public void serve(HttpServletRequest request, HttpServletResponse response, Repository repository, ServletConfig config) { } } + + private static class DummyScmProtocolProvider implements ScmProtocolProvider { + @Override + public String getType() { + return "git"; + } + + @Override + public ScmProtocol get(Repository repository) { + return new DummyHttpProtocol(repository); + } + } + + private interface UnknownScmProtocol extends ScmProtocol {} } diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java index 1e742a768a..6d01232fe3 100644 --- a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java @@ -62,7 +62,12 @@ public class InitializingHttpScmProtocolWrapperTest { pathInfoStoreProvider = mock(Provider.class); when(pathInfoStoreProvider.get()).thenReturn(pathInfoStore); - wrapper = new InitializingHttpScmProtocolWrapper(Providers.of(this.delegateServlet), Providers.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) {}; + wrapper = new InitializingHttpScmProtocolWrapper(Providers.of(this.delegateServlet), Providers.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) { + @Override + public String getType() { + return "git"; + } + }; when(scmConfiguration.getBaseUrl()).thenReturn("http://example.com/scm"); } @@ -127,6 +132,11 @@ public class InitializingHttpScmProtocolWrapperTest { verify(delegateServlet, times(2)).service(request, response, REPOSITORY); } + @Test(expected = IllegalArgumentException.class) + public void shouldFailForIllegalScmType() { + HttpScmProtocol httpScmProtocol = wrapper.get(new Repository("", "other", "space", "name")); + } + private Answer proceedInvocation() { return invocation -> { ((PermissionFilter.ContinuationServlet) invocation.getArgument(3)).doService(); @@ -135,12 +145,7 @@ public class InitializingHttpScmProtocolWrapperTest { } private OngoingStubbing mockSetPathInfo() { - return when(pathInfoStore.get()).thenReturn(new ScmPathInfo() { - @Override - public URI getApiRestUri() { - return URI.create("http://example.com/scm/api/rest/"); - } - }); + return when(pathInfoStore.get()).thenReturn(() -> URI.create("http://example.com/scm/api/rest/")); } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 235136938a..2d6b49a8e5 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -37,10 +37,8 @@ import com.google.common.collect.ImmutableSet; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; -import sonia.scm.repository.api.ScmProtocol; import java.io.IOException; -import java.util.Collections; import java.util.Set; /** @@ -69,12 +67,9 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- - public GitRepositoryServiceProvider(GitRepositoryHandler handler, - Repository repository, HttpScmProtocol httpScmProtocol) - { + public GitRepositoryServiceProvider(GitRepositoryHandler handler, Repository repository) { this.handler = handler; this.repository = repository; - this.httpScmProtocol = httpScmProtocol; this.context = new GitContext(handler.getDirectory(repository)); } @@ -238,11 +233,6 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider return new GitTagsCommand(context, repository); } - @Override - public Set getSupportedProtocols() { - return Collections.singleton(httpScmProtocol); - } - //~--- fields --------------------------------------------------------------- /** Field description */ @@ -253,6 +243,4 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private Repository repository; - - private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index d20eedca9f..b1e9143afd 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -38,7 +38,6 @@ import com.google.inject.Inject; import sonia.scm.plugin.Extension; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; -import sonia.scm.web.GitScmProtocolProviderWrapper; /** * @@ -49,10 +48,11 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver { public static final String TYPE = "git"; + private final GitRepositoryHandler handler; + @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitScmProtocolProviderWrapper providerWrapper) { + public GitRepositoryServiceResolver(GitRepositoryHandler handler) { this.handler = handler; - this.providerWrapper = providerWrapper; } @Override @@ -60,12 +60,9 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver { GitRepositoryServiceProvider provider = null; if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new GitRepositoryServiceProvider(handler, repository, providerWrapper.get(repository)); + provider = new GitRepositoryServiceProvider(handler, repository); } return provider; } - - private final GitRepositoryHandler handler; - private final GitScmProtocolProviderWrapper providerWrapper; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index 8ff0c6d421..3df7bcce3f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -9,9 +10,15 @@ import javax.inject.Provider; import javax.inject.Singleton; @Singleton +@Extension public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } + + @Override + public String getType() { + return "git"; + } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 8c280a9915..164eb4e13a 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -39,11 +39,9 @@ import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.api.Command; -import sonia.scm.repository.api.ScmProtocol; import java.io.File; import java.io.IOException; -import java.util.Collections; import java.util.EnumSet; import java.util.Set; @@ -78,11 +76,10 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- HgRepositoryServiceProvider(HgRepositoryHandler handler, - HgHookManager hookManager, Repository repository, HttpScmProtocol httpScmProtocol) + HgHookManager hookManager, Repository repository) { this.repository = repository; this.handler = handler; - this.httpScmProtocol = httpScmProtocol; this.repositoryDirectory = handler.getDirectory(repository); this.context = new HgCommandContext(hookManager, handler, repository, repositoryDirectory); @@ -260,11 +257,6 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider return new HgTagsCommand(context, repository); } - @Override - public Set getSupportedProtocols() { - return Collections.singleton(httpScmProtocol); - } - //~--- fields --------------------------------------------------------------- /** Field description */ @@ -278,6 +270,4 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private File repositoryDirectory; - - private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index c1accbad1a..f80dcd5ba8 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -38,7 +38,6 @@ import sonia.scm.plugin.Extension; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; -import sonia.scm.web.HgScmProtocolProviderWrapper; /** * @@ -48,59 +47,27 @@ import sonia.scm.web.HgScmProtocolProviderWrapper; public class HgRepositoryServiceResolver implements RepositoryServiceResolver { - /** Field description */ private static final String TYPE = "hg"; - //~--- constructors --------------------------------------------------------- + private HgRepositoryHandler handler; + private HgHookManager hookManager; - /** - * Constructs ... - * - * - * - * @param hookManager - * @param handler - */ @Inject public HgRepositoryServiceResolver(HgRepositoryHandler handler, - HgHookManager hookManager, HgScmProtocolProviderWrapper providerWrapper) + HgHookManager hookManager) { this.handler = handler; this.hookManager = hookManager; - this.providerWrapper = providerWrapper; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param repository - * - * @return - */ @Override - public HgRepositoryServiceProvider resolve(Repository repository) - { + public HgRepositoryServiceProvider resolve(Repository repository) { HgRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) - { - provider = new HgRepositoryServiceProvider(handler, hookManager, - repository, providerWrapper.get(repository)); + if (TYPE.equalsIgnoreCase(repository.getType())) { + provider = new HgRepositoryServiceProvider(handler, hookManager, repository); } return provider; } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private HgRepositoryHandler handler; - - /** Field description */ - private HgHookManager hookManager; - - private final HgScmProtocolProviderWrapper providerWrapper; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index e843f09ad4..5ea8e66501 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import javax.inject.Inject; @@ -9,9 +10,15 @@ import javax.inject.Provider; import javax.inject.Singleton; @Singleton +@Extension public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } + + @Override + public String getType() { + return "hg"; + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java index 6c08d35897..909daf7e36 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java @@ -38,10 +38,8 @@ import com.google.common.io.Closeables; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.api.Command; -import sonia.scm.repository.api.ScmProtocol; import java.io.IOException; -import java.util.Collections; import java.util.Set; /** @@ -61,18 +59,10 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * @param handler - * @param repository - * @param httpScmProtocol - */ SvnRepositoryServiceProvider(SvnRepositoryHandler handler, - Repository repository, HttpScmProtocol httpScmProtocol) + Repository repository) { this.repository = repository; - this.httpScmProtocol = httpScmProtocol; this.context = new SvnContext(handler.getDirectory(repository)); } @@ -188,11 +178,6 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider return new SvnUnbundleCommand(context, repository); } - @Override - public Set getSupportedProtocols() { - return Collections.singleton(httpScmProtocol); - } - //~--- fields --------------------------------------------------------------- /** Field description */ @@ -200,6 +185,4 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private final Repository repository; - - private final HttpScmProtocol httpScmProtocol; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java index 9f5ea234ce..c674a7827a 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java @@ -36,17 +36,17 @@ import com.google.inject.Inject; import sonia.scm.plugin.Extension; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; -import sonia.scm.web.SvnScmProtocolProviderWrapper; @Extension public class SvnRepositoryServiceResolver implements RepositoryServiceResolver { public static final String TYPE = "svn"; + private SvnRepositoryHandler handler; + @Inject - public SvnRepositoryServiceResolver(SvnRepositoryHandler handler, SvnScmProtocolProviderWrapper protocolWrapper) { + public SvnRepositoryServiceResolver(SvnRepositoryHandler handler) { this.handler = handler; - this.protocolWrapper = protocolWrapper; } @Override @@ -54,13 +54,9 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver { SvnRepositoryServiceProvider provider = null; if (TYPE.equalsIgnoreCase(repository.getType())) { - provider = new SvnRepositoryServiceProvider(handler, repository, protocolWrapper.get(repository)); + provider = new SvnRepositoryServiceProvider(handler, repository); } return provider; } - - private SvnRepositoryHandler handler; - - private final InitializingHttpScmProtocolWrapper protocolWrapper; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index ebcfa138bc..14b946acc7 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import sonia.scm.repository.spi.ScmProviderHttpServlet; @@ -14,10 +15,16 @@ import javax.servlet.ServletException; import java.util.Enumeration; @Singleton +@Extension public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { public static final String PARAMETER_SVN_PARENTPATH = "SVNParentPath"; + @Override + public String getType() { + return "svn"; + } + @Inject public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index ce716f2f6f..6675caac88 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -14,7 +14,6 @@ import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.ScmProtocol; -import java.util.Collection; import java.util.List; import static de.otto.edison.hal.Link.link; @@ -47,9 +46,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper supportedProtocols = repositoryService.getSupportedProtocols(); - List protocolLinks = supportedProtocols - .stream() + List protocolLinks = repositoryService.getSupportedProtocols() .map(protocol -> createProtocolLink(protocol, repository)) .collect(toList()); linksBuilder.array(protocolLinks); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index 4d0bb38785..04a4602a7c 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -30,8 +30,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import static java.util.Arrays.asList; import static java.util.Collections.singletonList; +import static java.util.stream.Stream.of; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; @@ -281,7 +281,7 @@ public class RepositoryRootResourceTest { @Test public void shouldCreateArrayOfProtocolUrls() throws Exception { mockRepository("space", "repo"); - when(service.getSupportedProtocols()).thenReturn(asList(new MockScmProtocol("http", "http://"), new MockScmProtocol("ssh", "ssh://"))); + when(service.getSupportedProtocols()).thenReturn(of(new MockScmProtocol("http", "http://"), new MockScmProtocol("ssh", "ssh://"))); MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo"); MockHttpResponse response = new MockHttpResponse(); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java index 0fbece9730..d60b62937e 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java @@ -20,9 +20,8 @@ import sonia.scm.repository.api.ScmProtocol; import java.net.URI; -import static java.util.Arrays.asList; -import static java.util.Collections.emptySet; import static java.util.Collections.singletonList; +import static java.util.stream.Stream.of; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -60,7 +59,7 @@ public class RepositoryToRepositoryDtoMapperTest { initMocks(this); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.isSupported(any(Command.class))).thenReturn(true); - when(repositoryService.getSupportedProtocols()).thenReturn(emptySet()); + when(repositoryService.getSupportedProtocols()).thenReturn(of()); when(scmPathInfoStore.get()).thenReturn(uriInfo); when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); } @@ -182,7 +181,7 @@ public class RepositoryToRepositoryDtoMapperTest { @Test public void shouldCreateCorrectProtocolLinks() { when(repositoryService.getSupportedProtocols()).thenReturn( - asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) ); RepositoryDto dto = mapper.map(createTestRepository()); @@ -194,7 +193,7 @@ public class RepositoryToRepositoryDtoMapperTest { @SubjectAware(username = "community") public void shouldCreateProtocolLinksForPullPermission() { when(repositoryService.getSupportedProtocols()).thenReturn( - asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) ); RepositoryDto dto = mapper.map(createTestRepository()); @@ -205,7 +204,7 @@ public class RepositoryToRepositoryDtoMapperTest { @SubjectAware(username = "unpriv") public void shouldNotCreateProtocolLinksWithoutPullPermission() { when(repositoryService.getSupportedProtocols()).thenReturn( - asList(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) + of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol")) ); RepositoryDto dto = mapper.map(createTestRepository()); From c5daacfd589ec0bf1e07dfc00532368dcf75d356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 13 Sep 2018 10:45:51 +0200 Subject: [PATCH 36/48] Format --- .../main/java/sonia/scm/repository/api/RepositoryService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java index 4d388609d8..b9e1cb2a5d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java @@ -362,7 +362,9 @@ public final class RepositoryService implements Closeable { public Stream getSupportedProtocols() { - return protocolProviders.stream().filter(provider -> provider.getType().equals(getRepository().getType())).map(this::createProviderInstanceForRepository); + return protocolProviders.stream() + .filter(provider -> provider.getType().equals(getRepository().getType())) + .map(this::createProviderInstanceForRepository); } private ScmProtocol createProviderInstanceForRepository(ScmProtocolProvider protocolProvider) { From a075962a66e8c56faeb4d8f1a241175103fcaaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 08:49:09 +0200 Subject: [PATCH 37/48] Introduce extension point for scm http requests --- .../spi/ScmProviderHttpServletFactory.java | 7 ++++++ .../main/java/sonia/scm/util/Decorators.java | 1 - .../src/main/java/sonia/scm/web/Git.java | 14 ++++++++++++ .../web/GitScmProtocolProviderWrapper.java | 3 ++- .../java/sonia/scm/web/GitServletModule.java | 3 +++ .../sonia/scm/web/ScmGitServletProvider.java | 22 +++++++++++++++++++ 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java rename {scm-webapp => scm-core}/src/main/java/sonia/scm/util/Decorators.java (99%) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java new file mode 100644 index 0000000000..1f49dec4ba --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java @@ -0,0 +1,7 @@ +package sonia.scm.repository.spi; + +import sonia.scm.DecoratorFactory; +import sonia.scm.plugin.ExtensionPoint; + +@ExtensionPoint +public interface ScmProviderHttpServletFactory extends DecoratorFactory {} diff --git a/scm-webapp/src/main/java/sonia/scm/util/Decorators.java b/scm-core/src/main/java/sonia/scm/util/Decorators.java similarity index 99% rename from scm-webapp/src/main/java/sonia/scm/util/Decorators.java rename to scm-core/src/main/java/sonia/scm/util/Decorators.java index 41c75660a9..6465631d03 100644 --- a/scm-webapp/src/main/java/sonia/scm/util/Decorators.java +++ b/scm-core/src/main/java/sonia/scm/util/Decorators.java @@ -37,7 +37,6 @@ package sonia.scm.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.DecoratorFactory; /** diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java new file mode 100644 index 0000000000..8bcf85c8f0 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java @@ -0,0 +1,14 @@ +package sonia.scm.web; + +import com.google.inject.BindingAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@BindingAnnotation +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@interface Git { +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index 3df7bcce3f..2924a27915 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -4,6 +4,7 @@ import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import javax.inject.Inject; import javax.inject.Provider; @@ -13,7 +14,7 @@ import javax.inject.Singleton; @Extension public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public GitScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public GitScmProtocolProviderWrapper(@Git Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index e731e01a62..8c7b30572f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -41,6 +41,7 @@ import org.mapstruct.factory.Mappers; import sonia.scm.api.v2.resources.GitConfigDtoToGitConfigMapper; import sonia.scm.api.v2.resources.GitConfigToGitConfigDtoMapper; import sonia.scm.plugin.Extension; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.web.lfs.LfsBlobStoreFactory; /** @@ -63,5 +64,7 @@ public class GitServletModule extends ServletModule bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass()); bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass()); + + bind(ScmProviderHttpServlet.class).annotatedWith(Git.class).toProvider(ScmGitServletProvider.class); } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java new file mode 100644 index 0000000000..2c7c8b19f9 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java @@ -0,0 +1,22 @@ +package sonia.scm.web; + +import com.google.inject.Inject; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletFactory; +import sonia.scm.util.Decorators; + +import javax.inject.Provider; +import java.util.Set; + +public class ScmGitServletProvider implements Provider { + + @Inject + private Provider scmGitServlet; + @Inject(optional = true) + private Set decoratorFactories; + + @Override + public ScmProviderHttpServlet get() { + return Decorators.decorate(scmGitServlet.get(), decoratorFactories); + } +} From 6ab5f58fe95b85fc3f5b86ed93bb8b6dbe932c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 09:15:46 +0200 Subject: [PATCH 38/48] Generalize servlet decorator structure --- .../spi/ScmProviderHttpServletDecorator.java | 28 +++++++++++++++++++ ...cmProviderHttpServletDecoratorFactory.java | 15 ++++++++++ .../spi/ScmProviderHttpServletFactory.java | 7 ----- .../sonia/scm/web/ScmGitServletProvider.java | 12 ++------ .../web/ScmProviderHttpServletProvider.java | 24 ++++++++++++++++ 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecorator.java create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecoratorFactory.java delete mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecorator.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecorator.java new file mode 100644 index 0000000000..c5dd55d277 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecorator.java @@ -0,0 +1,28 @@ +package sonia.scm.repository.spi; + +import sonia.scm.repository.Repository; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class ScmProviderHttpServletDecorator implements ScmProviderHttpServlet { + + private final ScmProviderHttpServlet object; + + public ScmProviderHttpServletDecorator(ScmProviderHttpServlet object) { + this.object = object; + } + + @Override + public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { + object.service(request, response, repository); + } + + @Override + public void init(ServletConfig config) throws ServletException { + object.init(config); + } +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecoratorFactory.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecoratorFactory.java new file mode 100644 index 0000000000..531a25e91d --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletDecoratorFactory.java @@ -0,0 +1,15 @@ +package sonia.scm.repository.spi; + +import sonia.scm.DecoratorFactory; +import sonia.scm.plugin.ExtensionPoint; + +@ExtensionPoint +public interface ScmProviderHttpServletDecoratorFactory extends DecoratorFactory { + /** + * Has to return true if this factory provides a decorator for the given scm type (eg. "git", "hg" or + * "svn"). + * @param type The current scm type this factory can provide a decorator for. + * @return true when the provided decorator should be used for the given scm type. + */ + boolean handlesScmType(String type); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java deleted file mode 100644 index 1f49dec4ba..0000000000 --- a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package sonia.scm.repository.spi; - -import sonia.scm.DecoratorFactory; -import sonia.scm.plugin.ExtensionPoint; - -@ExtensionPoint -public interface ScmProviderHttpServletFactory extends DecoratorFactory {} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java index 2c7c8b19f9..b8eb38de6d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java @@ -1,22 +1,16 @@ package sonia.scm.web; import com.google.inject.Inject; -import sonia.scm.repository.spi.ScmProviderHttpServlet; -import sonia.scm.repository.spi.ScmProviderHttpServletFactory; -import sonia.scm.util.Decorators; import javax.inject.Provider; -import java.util.Set; -public class ScmGitServletProvider implements Provider { +public class ScmGitServletProvider extends ScmProviderHttpServletProvider { @Inject private Provider scmGitServlet; - @Inject(optional = true) - private Set decoratorFactories; @Override - public ScmProviderHttpServlet get() { - return Decorators.decorate(scmGitServlet.get(), decoratorFactories); + protected ScmGitServlet getRootServlet() { + return scmGitServlet.get(); } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java new file mode 100644 index 0000000000..a9369d8f4e --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java @@ -0,0 +1,24 @@ +package sonia.scm.web; + +import com.google.inject.Inject; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; +import sonia.scm.util.Decorators; + +import javax.inject.Provider; +import java.util.Set; + +import static java.util.stream.Collectors.toList; + +public abstract class ScmProviderHttpServletProvider implements Provider { + + @Inject(optional = true) + private Set decoratorFactories; + + @Override + public ScmProviderHttpServlet get() { + return Decorators.decorate(getRootServlet(), decoratorFactories.stream().filter(d -> d.handlesScmType("git")).collect(toList())); + } + + protected abstract ScmProviderHttpServlet getRootServlet(); +} From 7de9f690613a626f322ae90d8606b63487b55e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 09:36:56 +0200 Subject: [PATCH 39/48] Add servlet decorators for hg and svn --- .../spi}/ScmProviderHttpServletProvider.java | 12 ++++++---- .../sonia/scm/web/ScmGitServletProvider.java | 12 +++++++--- .../src/main/java/sonia/scm/web/Hg.java | 14 ++++++++++++ .../sonia/scm/web/HgCGIServletProvider.java | 22 +++++++++++++++++++ .../scm/web/HgScmProtocolProviderWrapper.java | 3 ++- .../java/sonia/scm/web/HgServletModule.java | 3 +++ .../src/main/java/sonia/scm/web/Svn.java | 14 ++++++++++++ .../sonia/scm/web/SvnDAVServletProvider.java | 22 +++++++++++++++++++ .../web/SvnScmProtocolProviderWrapper.java | 2 +- .../java/sonia/scm/web/SvnServletModule.java | 3 +++ 10 files changed, 98 insertions(+), 9 deletions(-) rename {scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web => scm-core/src/main/java/sonia/scm/repository/spi}/ScmProviderHttpServletProvider.java (71%) create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java similarity index 71% rename from scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java rename to scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java index a9369d8f4e..991728e72c 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmProviderHttpServletProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java @@ -1,8 +1,6 @@ -package sonia.scm.web; +package sonia.scm.repository.spi; import com.google.inject.Inject; -import sonia.scm.repository.spi.ScmProviderHttpServlet; -import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; import sonia.scm.util.Decorators; import javax.inject.Provider; @@ -15,9 +13,15 @@ public abstract class ScmProviderHttpServletProvider implements Provider decoratorFactories; + private final String type; + + protected ScmProviderHttpServletProvider(String type) { + this.type = type; + } + @Override public ScmProviderHttpServlet get() { - return Decorators.decorate(getRootServlet(), decoratorFactories.stream().filter(d -> d.handlesScmType("git")).collect(toList())); + return Decorators.decorate(getRootServlet(), decoratorFactories.stream().filter(d -> d.handlesScmType(type)).collect(toList())); } protected abstract ScmProviderHttpServlet getRootServlet(); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java index b8eb38de6d..5e8ef80d3d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java @@ -1,16 +1,22 @@ package sonia.scm.web; import com.google.inject.Inject; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletProvider; import javax.inject.Provider; public class ScmGitServletProvider extends ScmProviderHttpServletProvider { @Inject - private Provider scmGitServlet; + private Provider servletProvider; + + public ScmGitServletProvider() { + super("git"); + } @Override - protected ScmGitServlet getRootServlet() { - return scmGitServlet.get(); + protected ScmProviderHttpServlet getRootServlet() { + return servletProvider.get(); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java new file mode 100644 index 0000000000..e4fe39e724 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java @@ -0,0 +1,14 @@ +package sonia.scm.web; + +import com.google.inject.BindingAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@BindingAnnotation +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@interface Hg { +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java new file mode 100644 index 0000000000..d17479b399 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java @@ -0,0 +1,22 @@ +package sonia.scm.web; + +import com.google.inject.Inject; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletProvider; + +import javax.inject.Provider; + +public class HgCGIServletProvider extends ScmProviderHttpServletProvider { + + @Inject + private Provider servletProvider; + + public HgCGIServletProvider() { + super("hg"); + } + + @Override + protected ScmProviderHttpServlet getRootServlet() { + return servletProvider.get(); + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index 5ea8e66501..1d75e63332 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -4,6 +4,7 @@ import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import javax.inject.Inject; import javax.inject.Provider; @@ -13,7 +14,7 @@ import javax.inject.Singleton; @Extension public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public HgScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public HgScmProtocolProviderWrapper(@Hg Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java index ba9ae3a0b9..6949be2ea9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java @@ -46,6 +46,7 @@ import sonia.scm.plugin.Extension; import sonia.scm.repository.HgContext; import sonia.scm.repository.HgContextProvider; import sonia.scm.repository.HgHookManager; +import sonia.scm.repository.spi.ScmProviderHttpServlet; /** * @@ -79,6 +80,8 @@ public class HgServletModule extends ServletModule bind(HgConfigPackagesToDtoMapper.class).to(Mappers.getMapper(HgConfigPackagesToDtoMapper.class).getClass()); bind(HgConfigInstallationsToDtoMapper.class); + bind(ScmProviderHttpServlet.class).annotatedWith(Hg.class).toProvider(HgCGIServletProvider.class); + // bind servlets serve(MAPPING_HOOK).with(HgHookCallbackServlet.class); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java new file mode 100644 index 0000000000..744c1a0939 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java @@ -0,0 +1,14 @@ +package sonia.scm.web; + +import com.google.inject.BindingAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@BindingAnnotation +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@interface Svn { +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java new file mode 100644 index 0000000000..586b277673 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java @@ -0,0 +1,22 @@ +package sonia.scm.web; + +import com.google.inject.Inject; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletProvider; + +import javax.inject.Provider; + +public class SvnDAVServletProvider extends ScmProviderHttpServletProvider { + + @Inject + private Provider servletProvider; + + public SvnDAVServletProvider() { + super("svn"); + } + + @Override + protected ScmProviderHttpServlet getRootServlet() { + return servletProvider.get(); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index 14b946acc7..ed47791793 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -26,7 +26,7 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr } @Inject - public SvnScmProtocolProviderWrapper(Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + public SvnScmProtocolProviderWrapper(@Svn Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 8526d6380a..cd47a2fa44 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -38,6 +38,7 @@ import org.mapstruct.factory.Mappers; import sonia.scm.api.v2.resources.SvnConfigDtoToSvnConfigMapper; import sonia.scm.api.v2.resources.SvnConfigToSvnConfigDtoMapper; import sonia.scm.plugin.Extension; +import sonia.scm.repository.spi.ScmProviderHttpServlet; /** * @@ -50,5 +51,7 @@ public class SvnServletModule extends ServletModule { protected void configureServlets() { bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass()); bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass()); + + bind(ScmProviderHttpServlet.class).annotatedWith(Svn.class).toProvider(SvnDAVServletProvider.class); } } From e88639ab814420983517f6eb86cc77dbf6b4ff00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 10:21:00 +0200 Subject: [PATCH 40/48] Implement permission filters as decorator for servlets --- .../InitializingHttpScmProtocolWrapper.java | 11 ++----- .../spi/ScmProviderHttpServletProvider.java | 7 +++- .../scm/web/filter/PermissionFilter.java | 19 +++++------ ...nitializingHttpScmProtocolWrapperTest.java | 33 +------------------ .../sonia/scm/web/GitPermissionFilter.java | 7 ++-- .../scm/web/GitPermissionFilterFactory.java | 29 ++++++++++++++++ .../web/GitScmProtocolProviderWrapper.java | 4 +-- .../scm/web/GitPermissionFilterTest.java | 3 +- .../sonia/scm/web/HgPermissionFilter.java | 7 ++-- .../scm/web/HgPermissionFilterFactory.java | 29 ++++++++++++++++ .../scm/web/HgScmProtocolProviderWrapper.java | 4 +-- .../sonia/scm/web/SvnPermissionFilter.java | 7 ++-- .../scm/web/SvnPermissionFilterFactory.java | 29 ++++++++++++++++ .../web/SvnScmProtocolProviderWrapper.java | 4 +-- 14 files changed, 122 insertions(+), 71 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 6e59470c5e..69ff0a83f5 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -6,7 +6,6 @@ import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; import sonia.scm.repository.api.ScmProtocolProvider; -import sonia.scm.web.filter.PermissionFilter; import javax.inject.Provider; import javax.servlet.ServletConfig; @@ -24,16 +23,14 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP private static final Logger logger = LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class); private final Provider delegateProvider; - private final Provider permissionFilterProvider; private final Provider uriInfoStore; private final ScmConfiguration scmConfiguration; private volatile boolean isInitialized = false; - protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider permissionFilterProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { this.delegateProvider = delegateProvider; - this.permissionFilterProvider = permissionFilterProvider; this.uriInfoStore = uriInfoStore; this.scmConfiguration = scmConfiguration; } @@ -89,11 +86,7 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP } } - permissionFilterProvider.get().executeIfPermitted( - request, - response, - repository, - () -> delegateProvider.get().service(request, response, repository)); + delegateProvider.get().service(request, response, repository); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java index 991728e72c..3793d4b935 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ScmProviderHttpServletProvider.java @@ -4,6 +4,7 @@ import com.google.inject.Inject; import sonia.scm.util.Decorators; import javax.inject.Provider; +import java.util.List; import java.util.Set; import static java.util.stream.Collectors.toList; @@ -21,7 +22,11 @@ public abstract class ScmProviderHttpServletProvider implements Provider d.handlesScmType(type)).collect(toList())); + return Decorators.decorate(getRootServlet(), getDecoratorsForType()); + } + + private List getDecoratorsForType() { + return decoratorFactories.stream().filter(d -> d.handlesScmType(type)).collect(toList()); } protected abstract ScmProviderHttpServlet getRootServlet(); diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index a01875fed0..328494a626 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -42,6 +42,8 @@ import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryPermissions; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecorator; import sonia.scm.security.Role; import sonia.scm.security.ScmSecurityException; import sonia.scm.util.HttpUtil; @@ -56,7 +58,7 @@ import java.io.IOException; * * @author Sebastian Sdorra */ -public abstract class PermissionFilter +public abstract class PermissionFilter extends ScmProviderHttpServletDecorator { /** the logger for PermissionFilter */ @@ -72,8 +74,9 @@ public abstract class PermissionFilter * * @since 1.21 */ - protected PermissionFilter(ScmConfiguration configuration) + protected PermissionFilter(ScmConfiguration configuration, ScmProviderHttpServlet delegate) { + super(delegate); this.configuration = configuration; } @@ -102,8 +105,9 @@ public abstract class PermissionFilter * @throws IOException * @throws ServletException */ - public void executeIfPermitted(HttpServletRequest request, - HttpServletResponse response, Repository repository, ContinuationServlet continuation) + @Override + public void service(HttpServletRequest request, + HttpServletResponse response, Repository repository) throws IOException, ServletException { Subject subject = SecurityUtils.getSubject(); @@ -118,7 +122,7 @@ public abstract class PermissionFilter getActionAsString(writeRequest), repository.getName(), getUserName(subject)); - continuation.doService(); + super.service(request, response, repository); } else { @@ -258,9 +262,4 @@ public abstract class PermissionFilter /** scm-manager global configuration */ private final ScmConfiguration configuration; - - @FunctionalInterface - public interface ContinuationServlet { - void doService() throws ServletException, IOException; - } } diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java index 6d01232fe3..8c910f92a9 100644 --- a/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapperTest.java @@ -5,13 +5,11 @@ import com.google.inject.util.Providers; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; -import org.mockito.stubbing.Answer; import org.mockito.stubbing.OngoingStubbing; import sonia.scm.api.v2.resources.ScmPathInfo; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.Repository; -import sonia.scm.web.filter.PermissionFilter; import javax.inject.Provider; import javax.servlet.ServletConfig; @@ -22,12 +20,7 @@ import java.io.IOException; import java.net.URI; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -40,8 +33,6 @@ public class InitializingHttpScmProtocolWrapperTest { @Mock private ScmProviderHttpServlet delegateServlet; @Mock - private PermissionFilter permissionFilter; - @Mock private ScmPathInfoStore pathInfoStore; @Mock private ScmConfiguration scmConfiguration; @@ -62,7 +53,7 @@ public class InitializingHttpScmProtocolWrapperTest { pathInfoStoreProvider = mock(Provider.class); when(pathInfoStoreProvider.get()).thenReturn(pathInfoStore); - wrapper = new InitializingHttpScmProtocolWrapper(Providers.of(this.delegateServlet), Providers.of(permissionFilter), pathInfoStoreProvider, scmConfiguration) { + wrapper = new InitializingHttpScmProtocolWrapper(Providers.of(this.delegateServlet), pathInfoStoreProvider, scmConfiguration) { @Override public String getType() { return "git"; @@ -98,8 +89,6 @@ public class InitializingHttpScmProtocolWrapperTest { @Test public void shouldInitializeAndDelegateRequestThroughFilter() throws ServletException, IOException { - doAnswer(proceedInvocation()). - when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); httpScmProtocol.serve(request, response, servletConfig); @@ -108,21 +97,8 @@ public class InitializingHttpScmProtocolWrapperTest { verify(delegateServlet).service(request, response, REPOSITORY); } - @Test - public void shouldNotDelegateRequestWhenFilterBlocks() throws ServletException, IOException { - doNothing(). - when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); - HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); - - httpScmProtocol.serve(request, response, servletConfig); - - verify(delegateServlet, never()).service(request, response, REPOSITORY); - } - @Test public void shouldInitializeOnlyOnce() throws ServletException, IOException { - doAnswer(proceedInvocation()). - when(permissionFilter).executeIfPermitted(same(request), same(response), same(REPOSITORY), any()); HttpScmProtocol httpScmProtocol = wrapper.get(REPOSITORY); httpScmProtocol.serve(request, response, servletConfig); @@ -137,13 +113,6 @@ public class InitializingHttpScmProtocolWrapperTest { HttpScmProtocol httpScmProtocol = wrapper.get(new Repository("", "other", "space", "name")); } - private Answer proceedInvocation() { - return invocation -> { - ((PermissionFilter.ContinuationServlet) invocation.getArgument(3)).doService(); - return null; - }; - } - private OngoingStubbing mockSetPathInfo() { return when(pathInfoStore.get()).thenReturn(() -> URI.create("http://example.com/scm/api/rest/")); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index e183555b3b..e38f26a309 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -34,11 +34,11 @@ package sonia.scm.web; import com.google.common.annotations.VisibleForTesting; -import com.google.inject.Inject; import org.eclipse.jgit.http.server.GitSmartHttpTools; import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.GitUtil; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; @@ -70,9 +70,8 @@ public class GitPermissionFilter extends PermissionFilter * * @param configuration scm main configuration */ - @Inject - public GitPermissionFilter(ScmConfiguration configuration) { - super(configuration); + public GitPermissionFilter(ScmConfiguration configuration, ScmProviderHttpServlet delegate) { + super(configuration, delegate); } @Override diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java new file mode 100644 index 0000000000..4ef76bdea1 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java @@ -0,0 +1,29 @@ +package sonia.scm.web; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; + +import javax.inject.Inject; + +@Extension +public class GitPermissionFilterFactory implements ScmProviderHttpServletDecoratorFactory { + + private final ScmConfiguration configuration; + + @Inject + public GitPermissionFilterFactory(ScmConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public boolean handlesScmType(String type) { + return "git".equals(type); + } + + @Override + public ScmProviderHttpServlet createDecorator(ScmProviderHttpServlet delegate) { + return new GitPermissionFilter(configuration, delegate); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index 2924a27915..073969ce91 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -14,8 +14,8 @@ import javax.inject.Singleton; @Extension public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public GitScmProtocolProviderWrapper(@Git Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { - super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); + public GitScmProtocolProviderWrapper(@Git Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, uriInfoStore, scmConfiguration); } @Override diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java index 8e7ff3d954..831402261b 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/GitPermissionFilterTest.java @@ -5,6 +5,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.util.HttpUtil; import javax.servlet.ServletOutputStream; @@ -28,7 +29,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class GitPermissionFilterTest { - private final GitPermissionFilter permissionFilter = new GitPermissionFilter(new ScmConfiguration()); + private final GitPermissionFilter permissionFilter = new GitPermissionFilter(new ScmConfiguration(), mock(ScmProviderHttpServlet.class)); @Mock private HttpServletResponse response; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index a2dccb30c9..7f92cc0357 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -34,8 +34,8 @@ package sonia.scm.web; import com.google.common.collect.ImmutableSet; -import com.google.inject.Inject; import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; @@ -51,10 +51,9 @@ public class HgPermissionFilter extends PermissionFilter private static final Set READ_METHODS = ImmutableSet.of("GET", "HEAD", "OPTIONS", "TRACE"); - @Inject - public HgPermissionFilter(ScmConfiguration configuration) + public HgPermissionFilter(ScmConfiguration configuration, ScmProviderHttpServlet delegate) { - super(configuration); + super(configuration, delegate); } @Override diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java new file mode 100644 index 0000000000..584a8113ab --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java @@ -0,0 +1,29 @@ +package sonia.scm.web; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; + +import javax.inject.Inject; + +@Extension +public class HgPermissionFilterFactory implements ScmProviderHttpServletDecoratorFactory { + + private final ScmConfiguration configuration; + + @Inject + public HgPermissionFilterFactory(ScmConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public boolean handlesScmType(String type) { + return "hg".equals(type); + } + + @Override + public ScmProviderHttpServlet createDecorator(ScmProviderHttpServlet delegate) { + return new HgPermissionFilter(configuration, delegate); + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index 1d75e63332..fcd80a880c 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -14,8 +14,8 @@ import javax.inject.Singleton; @Extension public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper { @Inject - public HgScmProtocolProviderWrapper(@Hg Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { - super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); + public HgScmProtocolProviderWrapper(@Hg Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, uriInfoStore, scmConfiguration); } @Override diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 8918b8fa90..2c0a1e65ff 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -34,11 +34,11 @@ package sonia.scm.web; import com.google.common.collect.ImmutableSet; -import com.google.inject.Inject; import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.ScmSvnErrorCode; import sonia.scm.repository.SvnUtil; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.web.filter.PermissionFilter; import javax.servlet.http.HttpServletRequest; @@ -65,10 +65,9 @@ public class SvnPermissionFilter extends PermissionFilter * * @param configuration */ - @Inject - public SvnPermissionFilter(ScmConfiguration configuration) + public SvnPermissionFilter(ScmConfiguration configuration, ScmProviderHttpServlet delegate) { - super(configuration); + super(configuration, delegate); } //~--- methods -------------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java new file mode 100644 index 0000000000..cd4a7600aa --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java @@ -0,0 +1,29 @@ +package sonia.scm.web; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; + +import javax.inject.Inject; + +@Extension +public class SvnPermissionFilterFactory implements ScmProviderHttpServletDecoratorFactory { + + private final ScmConfiguration configuration; + + @Inject + public SvnPermissionFilterFactory(ScmConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public boolean handlesScmType(String type) { + return "svn".equals(type); + } + + @Override + public ScmProviderHttpServlet createDecorator(ScmProviderHttpServlet delegate) { + return new SvnPermissionFilter(configuration, delegate); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index ed47791793..dbb8d5a84d 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -26,8 +26,8 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr } @Inject - public SvnScmProtocolProviderWrapper(@Svn Provider servletProvider, Provider permissionFilter, Provider uriInfoStore, ScmConfiguration scmConfiguration) { - super(servletProvider, permissionFilter, uriInfoStore, scmConfiguration); + public SvnScmProtocolProviderWrapper(@Svn Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) { + super(servletProvider, uriInfoStore, scmConfiguration); } @Override From 4d60ebd54eb894f711140e38143e24142fd41a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 10:31:16 +0200 Subject: [PATCH 41/48] Use constants for repository types --- .../scm/repository/spi/GitRepositoryServiceResolver.java | 4 +--- .../main/java/sonia/scm/web/GitPermissionFilterFactory.java | 3 ++- .../java/sonia/scm/web/GitScmProtocolProviderWrapper.java | 3 ++- .../src/main/java/sonia/scm/web/ScmGitServletProvider.java | 3 ++- .../sonia/scm/repository/spi/HgRepositoryServiceResolver.java | 4 +--- .../src/main/java/sonia/scm/web/HgCGIServletProvider.java | 3 ++- .../main/java/sonia/scm/web/HgPermissionFilterFactory.java | 3 ++- .../main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java | 3 ++- .../scm/repository/spi/SvnRepositoryServiceResolver.java | 4 +--- .../src/main/java/sonia/scm/web/SvnDAVServletProvider.java | 3 ++- .../main/java/sonia/scm/web/SvnPermissionFilterFactory.java | 3 ++- .../java/sonia/scm/web/SvnScmProtocolProviderWrapper.java | 3 ++- 12 files changed, 21 insertions(+), 18 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index b1e9143afd..deca141556 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -46,8 +46,6 @@ import sonia.scm.repository.Repository; @Extension public class GitRepositoryServiceResolver implements RepositoryServiceResolver { - public static final String TYPE = "git"; - private final GitRepositoryHandler handler; @Inject @@ -59,7 +57,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver { public GitRepositoryServiceProvider resolve(Repository repository) { GitRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) { + if (GitRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { provider = new GitRepositoryServiceProvider(handler, repository); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java index 4ef76bdea1..c358da5fb1 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilterFactory.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; @@ -19,7 +20,7 @@ public class GitPermissionFilterFactory implements ScmProviderHttpServletDecorat @Override public boolean handlesScmType(String type) { - return "git".equals(type); + return GitRepositoryHandler.TYPE_NAME.equals(type); } @Override diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java index 073969ce91..8273f3950e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java @@ -3,6 +3,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import sonia.scm.repository.spi.ScmProviderHttpServlet; @@ -20,6 +21,6 @@ public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr @Override public String getType() { - return "git"; + return GitRepositoryHandler.TYPE_NAME; } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java index 5e8ef80d3d..56a9e358be 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServletProvider.java @@ -1,6 +1,7 @@ package sonia.scm.web; import com.google.inject.Inject; +import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletProvider; @@ -12,7 +13,7 @@ public class ScmGitServletProvider extends ScmProviderHttpServletProvider { private Provider servletProvider; public ScmGitServletProvider() { - super("git"); + super(GitRepositoryHandler.TYPE_NAME); } @Override diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index f80dcd5ba8..d6d04ee017 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -47,8 +47,6 @@ import sonia.scm.repository.Repository; public class HgRepositoryServiceResolver implements RepositoryServiceResolver { - private static final String TYPE = "hg"; - private HgRepositoryHandler handler; private HgHookManager hookManager; @@ -64,7 +62,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver public HgRepositoryServiceProvider resolve(Repository repository) { HgRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) { + if (HgRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { provider = new HgRepositoryServiceProvider(handler, hookManager, repository); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java index d17479b399..db7a6be7b3 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServletProvider.java @@ -1,6 +1,7 @@ package sonia.scm.web; import com.google.inject.Inject; +import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletProvider; @@ -12,7 +13,7 @@ public class HgCGIServletProvider extends ScmProviderHttpServletProvider { private Provider servletProvider; public HgCGIServletProvider() { - super("hg"); + super(HgRepositoryHandler.TYPE_NAME); } @Override diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java index 584a8113ab..90f53a1fea 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilterFactory.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; @@ -19,7 +20,7 @@ public class HgPermissionFilterFactory implements ScmProviderHttpServletDecorato @Override public boolean handlesScmType(String type) { - return "hg".equals(type); + return HgRepositoryHandler.TYPE_NAME.equals(type); } @Override diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java index fcd80a880c..72382f16bc 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java @@ -3,6 +3,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import sonia.scm.repository.spi.ScmProviderHttpServlet; @@ -20,6 +21,6 @@ public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWra @Override public String getType() { - return "hg"; + return HgRepositoryHandler.TYPE_NAME; } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java index c674a7827a..763b5f445e 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java @@ -40,8 +40,6 @@ import sonia.scm.repository.SvnRepositoryHandler; @Extension public class SvnRepositoryServiceResolver implements RepositoryServiceResolver { - public static final String TYPE = "svn"; - private SvnRepositoryHandler handler; @Inject @@ -53,7 +51,7 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver { public SvnRepositoryServiceProvider resolve(Repository repository) { SvnRepositoryServiceProvider provider = null; - if (TYPE.equalsIgnoreCase(repository.getType())) { + if (SvnRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { provider = new SvnRepositoryServiceProvider(handler, repository); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java index 586b277673..d221504256 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServletProvider.java @@ -1,6 +1,7 @@ package sonia.scm.web; import com.google.inject.Inject; +import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletProvider; @@ -12,7 +13,7 @@ public class SvnDAVServletProvider extends ScmProviderHttpServletProvider { private Provider servletProvider; public SvnDAVServletProvider() { - super("svn"); + super(SvnRepositoryHandler.TYPE_NAME); } @Override diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java index cd4a7600aa..882cb8c54f 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilterFactory.java @@ -2,6 +2,7 @@ package sonia.scm.web; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; @@ -19,7 +20,7 @@ public class SvnPermissionFilterFactory implements ScmProviderHttpServletDecorat @Override public boolean handlesScmType(String type) { - return "svn".equals(type); + return SvnRepositoryHandler.TYPE_NAME.equals(type); } @Override diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java index dbb8d5a84d..fb7d921742 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java @@ -3,6 +3,7 @@ package sonia.scm.web; import sonia.scm.api.v2.resources.ScmPathInfoStore; import sonia.scm.config.ScmConfiguration; import sonia.scm.plugin.Extension; +import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper; import sonia.scm.repository.spi.ScmProviderHttpServlet; @@ -22,7 +23,7 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr @Override public String getType() { - return "svn"; + return SvnRepositoryHandler.TYPE_NAME; } @Inject From 8ccd0c1b2d46d02139bb942be6910214b21f54ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 11:01:25 +0200 Subject: [PATCH 42/48] Implement gzip filter for svn as extension --- .../java/sonia/scm/web/SvnGZipFilter.java | 58 ++++++++++++------- .../sonia/scm/web/SvnGZipFilterFactory.java | 28 +++++++++ 2 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilterFactory.java diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java index 65afefbb28..7cc78180ff 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java @@ -34,38 +34,34 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- -import com.google.inject.Inject; -import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.filter.GZipFilter; +import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; - -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; +import sonia.scm.repository.spi.ScmProviderHttpServlet; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ -@Singleton -public class SvnGZipFilter extends GZipFilter +public class SvnGZipFilter extends GZipFilter implements ScmProviderHttpServlet { - /** - * the logger for SvnGZipFilter - */ - private static final Logger logger = - LoggerFactory.getLogger(SvnGZipFilter.class); + private static final Logger logger = LoggerFactory.getLogger(SvnGZipFilter.class); + + private final SvnRepositoryHandler handler; + private final ScmProviderHttpServlet delegate; //~--- constructors --------------------------------------------------------- @@ -75,10 +71,10 @@ public class SvnGZipFilter extends GZipFilter * * @param handler */ - @Inject - public SvnGZipFilter(SvnRepositoryHandler handler) + public SvnGZipFilter(SvnRepositoryHandler handler, ScmProviderHttpServlet delegate) { this.handler = handler; + this.delegate = delegate; } //~--- methods -------------------------------------------------------------- @@ -134,8 +130,30 @@ public class SvnGZipFilter extends GZipFilter } } - //~--- fields --------------------------------------------------------------- + @Override + public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { + if (handler.getConfig().isEnabledGZip()) + { + if (logger.isTraceEnabled()) + { + logger.trace("encode svn request with gzip"); + } - /** Field description */ - private SvnRepositoryHandler handler; + super.doFilter(request, response, (servletRequest, servletResponse) -> delegate.service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse, repository)); + } + else + { + if (logger.isTraceEnabled()) + { + logger.trace("skip gzip encoding"); + } + + delegate.service(request, response, repository); + } + } + + @Override + public void init(ServletConfig config) throws ServletException { + delegate.init(config); + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilterFactory.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilterFactory.java new file mode 100644 index 0000000000..e2774106fa --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilterFactory.java @@ -0,0 +1,28 @@ +package sonia.scm.web; + +import com.google.inject.Inject; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.repository.spi.ScmProviderHttpServletDecoratorFactory; + +@Extension +public class SvnGZipFilterFactory implements ScmProviderHttpServletDecoratorFactory { + + private final SvnRepositoryHandler handler; + + @Inject + public SvnGZipFilterFactory(SvnRepositoryHandler handler) { + this.handler = handler; + } + + @Override + public boolean handlesScmType(String type) { + return SvnRepositoryHandler.TYPE_NAME.equals(type); + } + + @Override + public ScmProviderHttpServlet createDecorator(ScmProviderHttpServlet delegate) { + return new SvnGZipFilter(handler, delegate); + } +} From cd344664aafe87e230218eb3f7a31b5b3d0f2274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 11:30:05 +0200 Subject: [PATCH 43/48] Test permission filter --- .../scm/web/filter/PermissionFilterTest.java | 74 +++++++++++++++++++ .../src/test/resources/sonia/scm/shiro.ini | 8 +- 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 scm-core/src/test/java/sonia/scm/web/filter/PermissionFilterTest.java diff --git a/scm-core/src/test/java/sonia/scm/web/filter/PermissionFilterTest.java b/scm-core/src/test/java/sonia/scm/web/filter/PermissionFilterTest.java new file mode 100644 index 0000000000..9fa65d51b8 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/web/filter/PermissionFilterTest.java @@ -0,0 +1,74 @@ +package sonia.scm.web.filter; + +import com.github.sdorra.shiro.ShiroRule; +import com.github.sdorra.shiro.SubjectAware; +import org.junit.Rule; +import org.junit.Test; +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.Repository; +import sonia.scm.repository.spi.ScmProviderHttpServlet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +@SubjectAware(configuration = "classpath:sonia/scm/shiro.ini") +public class PermissionFilterTest { + + public static final Repository REPOSITORY = new Repository("1", "git", "space", "name"); + + @Rule + public final ShiroRule shiroRule = new ShiroRule(); + + private final ScmProviderHttpServlet delegateServlet = mock(ScmProviderHttpServlet.class); + + private final PermissionFilter permissionFilter = new PermissionFilter(new ScmConfiguration(), delegateServlet) { + @Override + protected boolean isWriteRequest(HttpServletRequest request) { + return writeRequest; + } + }; + + private final HttpServletRequest request = mock(HttpServletRequest.class); + private final HttpServletResponse response = mock(HttpServletResponse.class); + + private boolean writeRequest = false; + + @Test + @SubjectAware(username = "reader", password = "secret") + public void shouldPassForReaderOnReadRequest() throws IOException, ServletException { + writeRequest = false; + + permissionFilter.service(request, response, REPOSITORY); + + verify(delegateServlet).service(request, response, REPOSITORY); + } + + @Test + @SubjectAware(username = "reader", password = "secret") + public void shouldBlockForReaderOnWriteRequest() throws IOException, ServletException { + writeRequest = true; + + permissionFilter.service(request, response, REPOSITORY); + + verify(response).sendError(eq(401), anyString()); + verify(delegateServlet, never()).service(request, response, REPOSITORY); + } + + @Test + @SubjectAware(username = "writer", password = "secret") + public void shouldPassForWriterOnWriteRequest() throws IOException, ServletException { + writeRequest = true; + + permissionFilter.service(request, response, REPOSITORY); + + verify(delegateServlet).service(request, response, REPOSITORY); + } +} diff --git a/scm-core/src/test/resources/sonia/scm/shiro.ini b/scm-core/src/test/resources/sonia/scm/shiro.ini index e87c81b097..fbdd35ba50 100644 --- a/scm-core/src/test/resources/sonia/scm/shiro.ini +++ b/scm-core/src/test/resources/sonia/scm/shiro.ini @@ -1,6 +1,12 @@ [users] trillian = secret, user +admin = secret, admin +writer = secret, repo_write +reader = secret, repo_read +unpriv = secret [roles] admin = * -user = something:* \ No newline at end of file +user = something:* +repo_read = "repository:read:1" +repo_write = "repository:push:1" From 37ea231340c62307fafe1358b4af24b2f6aad18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 14 Sep 2018 12:11:07 +0200 Subject: [PATCH 44/48] Cleanup smells --- .../sonia/scm/repository/RepositoryNotFoundException.java | 8 ++++---- .../java/sonia/scm/repository/api/RepositoryService.java | 2 +- .../spi/InitializingHttpScmProtocolWrapper.java | 6 +++--- .../api/v2/resources/RepositoryToRepositoryDtoMapper.java | 6 ++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java index 1208596348..9dd866daa4 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryNotFoundException.java @@ -44,8 +44,8 @@ import sonia.scm.NotFoundException; public class RepositoryNotFoundException extends NotFoundException { - /** Field description */ private static final long serialVersionUID = -6583078808900520166L; + private static final String TYPE_REPOSITORY = "repository"; //~--- constructors --------------------------------------------------------- @@ -55,14 +55,14 @@ public class RepositoryNotFoundException extends NotFoundException * */ public RepositoryNotFoundException(Repository repository) { - super("repository", repository.getName() + "/" + repository.getNamespace()); + super(TYPE_REPOSITORY, repository.getName() + "/" + repository.getNamespace()); } public RepositoryNotFoundException(String repositoryId) { - super("repository", repositoryId); + super(TYPE_REPOSITORY, repositoryId); } public RepositoryNotFoundException(NamespaceAndName namespaceAndName) { - super("repository", namespaceAndName.toString()); + super(TYPE_REPOSITORY, namespaceAndName.toString()); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java index b9e1cb2a5d..452203dd09 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java @@ -363,7 +363,7 @@ public final class RepositoryService implements Closeable { public Stream getSupportedProtocols() { return protocolProviders.stream() - .filter(provider -> provider.getType().equals(getRepository().getType())) + .filter(protocolProvider -> protocolProvider.getType().equals(getRepository().getType())) .map(this::createProviderInstanceForRepository); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java index 69ff0a83f5..0a94b1e6bf 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java @@ -44,7 +44,7 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP if (!repository.getType().equals(getType())) { throw new IllegalArgumentException("cannot handle repository with type " + repository.getType() + " with protocol for type " + getType()); } - return new ProtocolWrapper(repository); + return new ProtocolWrapper(repository, computeBasePath()); } private String computeBasePath() { @@ -70,8 +70,8 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP private class ProtocolWrapper extends HttpScmProtocol { - public ProtocolWrapper(Repository repository) { - super(repository, computeBasePath()); + public ProtocolWrapper(Repository repository, String basePath) { + super(repository, basePath); } @Override diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java index 6675caac88..29a4107aad 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapper.java @@ -29,8 +29,6 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper protocolLinks = repositoryService.getSupportedProtocols() - .map(protocol -> createProtocolLink(protocol, repository)) + .map(this::createProtocolLink) .collect(toList()); linksBuilder.array(protocolLinks); } @@ -63,7 +61,7 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper Date: Mon, 17 Sep 2018 09:15:40 +0200 Subject: [PATCH 45/48] Cleanup names, dead code and logging --- .../scm/api/v2/resources/LinkBuilder.java | 16 ++-- .../InitializingHttpScmProtocolWrapper.java | 2 +- .../resources/RepositoryRootResource.java | 40 +-------- .../scm/api/v2/resources/ResourceLinks.java | 82 +++++++++---------- .../repository/DefaultRepositoryManager.java | 3 - .../DefaultRepositoryManagerPerfTest.java | 2 - .../DefaultRepositoryManagerTest.java | 7 +- 7 files changed, 53 insertions(+), 99 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java b/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java index 13ae04b093..0797134c9f 100644 --- a/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java +++ b/scm-core/src/main/java/sonia/scm/api/v2/resources/LinkBuilder.java @@ -13,7 +13,7 @@ import java.util.Arrays; * builder for each method. * *
- * LinkBuilder builder = new LinkBuilder(uriInfo, MainResource.class, SubResource.class);
+ * LinkBuilder builder = new LinkBuilder(pathInfo, MainResource.class, SubResource.class);
  * Link link = builder
  *     .method("sub")
  *     .parameters("param")
@@ -24,16 +24,16 @@ import java.util.Arrays;
  */
 @SuppressWarnings("WeakerAccess") // Non-public will result in IllegalAccessError for plugins
 public class LinkBuilder {
-  private final ScmPathInfo uriInfo;
+  private final ScmPathInfo pathInfo;
   private final Class[] classes;
   private final ImmutableList calls;
 
-  public LinkBuilder(ScmPathInfo uriInfo, Class... classes) {
-    this(uriInfo, classes, ImmutableList.of());
+  public LinkBuilder(ScmPathInfo pathInfo, Class... classes) {
+    this(pathInfo, classes, ImmutableList.of());
   }
 
-  private LinkBuilder(ScmPathInfo uriInfo, Class[] classes, ImmutableList calls) {
-    this.uriInfo = uriInfo;
+  private LinkBuilder(ScmPathInfo pathInfo, Class[] classes, ImmutableList calls) {
+    this.pathInfo = pathInfo;
     this.classes = classes;
     this.calls = calls;
   }
@@ -50,7 +50,7 @@ public class LinkBuilder {
       throw new IllegalStateException("not enough methods for all classes");
     }
 
-    URI baseUri = uriInfo.getApiRestUri();
+    URI baseUri = pathInfo.getApiRestUri();
     URI relativeUri = createRelativeUri();
     return baseUri.resolve(relativeUri);
   }
@@ -60,7 +60,7 @@ public class LinkBuilder {
   }
 
   private LinkBuilder add(String method, String[] parameters) {
-    return new LinkBuilder(uriInfo, classes, appendNewCall(method, parameters));
+    return new LinkBuilder(pathInfo, classes, appendNewCall(method, parameters));
   }
 
   private ImmutableList appendNewCall(String method, String[] parameters) {
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
index 0a94b1e6bf..57de407edc 100644
--- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
@@ -64,7 +64,7 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP
   }
 
   private String getPathFromConfiguration() {
-    logger.debug("using base path from configuration: " + scmConfiguration.getBaseUrl());
+    logger.debug("using base path from configuration: {}", scmConfiguration.getBaseUrl());
     return scmConfiguration.getBaseUrl();
   }
 
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
index 6ad9b6257e..d5ea6c88de 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
@@ -42,7 +42,6 @@ import sonia.scm.repository.Repository;
 import sonia.scm.repository.RepositoryManager;
 import sonia.scm.repository.RepositoryTypePredicate;
 import sonia.scm.template.Viewable;
-import sonia.scm.util.HttpUtil;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.GET;
@@ -98,13 +97,12 @@ public class RepositoryRootResource
   @Produces(MediaType.TEXT_HTML)
   public Viewable renderRepositoriesRoot(@Context HttpServletRequest request, @PathParam("type") final String type)
   {
-    String baseUrl = HttpUtil.getCompleteUrl(request);
     //J-
     Collection unsortedRepositories =
       Collections2.transform( 
         Collections2.filter(
             repositoryManager.getAll(), new RepositoryTypePredicate(type))
-        , new RepositoryTransformFunction(baseUrl)
+        , new RepositoryTransformFunction()
       );
     
     List repositories = Ordering.from(
@@ -130,17 +128,9 @@ public class RepositoryRootResource
   public static class RepositoryTemplateElement
   {
 
-    /**
-     * Constructs ...
-     *
-     *
-     * @param repository
-     * @param baseUrl
-     */
-    public RepositoryTemplateElement(Repository repository, String baseUrl)
+    public RepositoryTemplateElement(Repository repository)
     {
       this.repository = repository;
-      this.baseUrl = baseUrl;
     }
 
     //~--- get methods --------------------------------------------------------
@@ -169,9 +159,6 @@ public class RepositoryRootResource
 
     //~--- fields -------------------------------------------------------------
 
-    /** Field description */
-    private String baseUrl;
-
     /** Field description */
     private Repository repository;
 
@@ -217,31 +204,10 @@ public class RepositoryRootResource
   private static class RepositoryTransformFunction
     implements Function
   {
-
-    public RepositoryTransformFunction(String baseUrl)
-    {
-      this.baseUrl = baseUrl;
-    }
-
-    //~--- methods ------------------------------------------------------------
-
-    /**
-     * Method description
-     *
-     *
-     * @param repository
-     *
-     * @return
-     */
     @Override
     public RepositoryTemplateElement apply(Repository repository)
     {
-      return new RepositoryTemplateElement(repository, baseUrl);
+      return new RepositoryTemplateElement(repository);
     }
-
-    //~--- fields -------------------------------------------------------------
-
-    /** Field description */
-    private String baseUrl;
   }
 }
diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
index 59d7ccaa27..35444bb715 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
@@ -26,8 +26,8 @@ class ResourceLinks {
   static class GroupLinks {
     private final LinkBuilder groupLinkBuilder;
 
-    GroupLinks(ScmPathInfo uriInfo) {
-      groupLinkBuilder = new LinkBuilder(uriInfo, GroupRootResource.class, GroupResource.class);
+    GroupLinks(ScmPathInfo pathInfo) {
+      groupLinkBuilder = new LinkBuilder(pathInfo, GroupRootResource.class, GroupResource.class);
     }
 
     String self(String name) {
@@ -50,8 +50,8 @@ class ResourceLinks {
   static class GroupCollectionLinks {
     private final LinkBuilder collectionLinkBuilder;
 
-    GroupCollectionLinks(ScmPathInfo uriInfo) {
-      collectionLinkBuilder = new LinkBuilder(uriInfo, GroupRootResource.class, GroupCollectionResource.class);
+    GroupCollectionLinks(ScmPathInfo pathInfo) {
+      collectionLinkBuilder = new LinkBuilder(pathInfo, GroupRootResource.class, GroupCollectionResource.class);
     }
 
     String self() {
@@ -70,8 +70,8 @@ class ResourceLinks {
   static class UserLinks {
     private final LinkBuilder userLinkBuilder;
 
-    UserLinks(ScmPathInfo uriInfo) {
-      userLinkBuilder = new LinkBuilder(uriInfo, UserRootResource.class, UserResource.class);
+    UserLinks(ScmPathInfo pathInfo) {
+      userLinkBuilder = new LinkBuilder(pathInfo, UserRootResource.class, UserResource.class);
     }
 
     String self(String name) {
@@ -94,8 +94,8 @@ class ResourceLinks {
   static class UserCollectionLinks {
     private final LinkBuilder collectionLinkBuilder;
 
-    UserCollectionLinks(ScmPathInfo uriInfo) {
-      collectionLinkBuilder = new LinkBuilder(uriInfo, UserRootResource.class, UserCollectionResource.class);
+    UserCollectionLinks(ScmPathInfo pathInfo) {
+      collectionLinkBuilder = new LinkBuilder(pathInfo, UserRootResource.class, UserCollectionResource.class);
     }
 
     String self() {
@@ -114,8 +114,8 @@ class ResourceLinks {
   static class ConfigLinks {
     private final LinkBuilder configLinkBuilder;
 
-    ConfigLinks(ScmPathInfo uriInfo) {
-      configLinkBuilder = new LinkBuilder(uriInfo, ConfigResource.class);
+    ConfigLinks(ScmPathInfo pathInfo) {
+      configLinkBuilder = new LinkBuilder(pathInfo, ConfigResource.class);
     }
 
     String self() {
@@ -133,11 +133,9 @@ class ResourceLinks {
 
   static class RepositoryLinks {
     private final LinkBuilder repositoryLinkBuilder;
-    private final ScmPathInfo uriInfo;
 
-    RepositoryLinks(ScmPathInfo uriInfo) {
-      repositoryLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class);
-      this.uriInfo = uriInfo;
+    RepositoryLinks(ScmPathInfo pathInfo) {
+      repositoryLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class);
     }
 
     String self(String namespace, String name) {
@@ -160,8 +158,8 @@ class ResourceLinks {
   static class RepositoryCollectionLinks {
     private final LinkBuilder collectionLinkBuilder;
 
-    RepositoryCollectionLinks(ScmPathInfo uriInfo) {
-      collectionLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryCollectionResource.class);
+    RepositoryCollectionLinks(ScmPathInfo pathInfo) {
+      collectionLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryCollectionResource.class);
     }
 
     String self() {
@@ -180,8 +178,8 @@ class ResourceLinks {
   static class RepositoryTypeLinks {
     private final LinkBuilder repositoryTypeLinkBuilder;
 
-    RepositoryTypeLinks(ScmPathInfo uriInfo) {
-      repositoryTypeLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeResource.class);
+    RepositoryTypeLinks(ScmPathInfo pathInfo) {
+      repositoryTypeLinkBuilder = new LinkBuilder(pathInfo, RepositoryTypeRootResource.class, RepositoryTypeResource.class);
     }
 
     String self(String name) {
@@ -196,8 +194,8 @@ class ResourceLinks {
   static class RepositoryTypeCollectionLinks {
     private final LinkBuilder collectionLinkBuilder;
 
-    RepositoryTypeCollectionLinks(ScmPathInfo uriInfo) {
-      collectionLinkBuilder = new LinkBuilder(uriInfo, RepositoryTypeRootResource.class, RepositoryTypeCollectionResource.class);
+    RepositoryTypeCollectionLinks(ScmPathInfo pathInfo) {
+      collectionLinkBuilder = new LinkBuilder(pathInfo, RepositoryTypeRootResource.class, RepositoryTypeCollectionResource.class);
     }
 
     String self() {
@@ -213,8 +211,8 @@ class ResourceLinks {
   static class TagCollectionLinks {
     private final LinkBuilder tagLinkBuilder;
 
-    TagCollectionLinks(ScmPathInfo uriInfo) {
-      tagLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, TagRootResource.class);
+    TagCollectionLinks(ScmPathInfo pathInfo) {
+      tagLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, TagRootResource.class);
     }
 
     String self(String namespace, String name, String tagName) {
@@ -233,8 +231,8 @@ class ResourceLinks {
   static class DiffLinks {
     private final LinkBuilder diffLinkBuilder;
 
-    DiffLinks(ScmPathInfo uriInfo) {
-      diffLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, DiffRootResource.class);
+    DiffLinks(ScmPathInfo pathInfo) {
+      diffLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, DiffRootResource.class);
     }
 
     String self(String namespace, String name, String id) {
@@ -253,8 +251,8 @@ class ResourceLinks {
   static class BranchLinks {
     private final LinkBuilder branchLinkBuilder;
 
-    BranchLinks(ScmPathInfo uriInfo) {
-      branchLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class);
+    BranchLinks(ScmPathInfo pathInfo) {
+      branchLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class);
     }
 
     String self(NamespaceAndName namespaceAndName, String branch) {
@@ -273,8 +271,8 @@ class ResourceLinks {
   static class BranchCollectionLinks {
     private final LinkBuilder branchLinkBuilder;
 
-    BranchCollectionLinks(ScmPathInfo uriInfo) {
-      branchLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class);
+    BranchCollectionLinks(ScmPathInfo pathInfo) {
+      branchLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, BranchRootResource.class);
     }
 
     String self(String namespace, String name) {
@@ -289,8 +287,8 @@ class ResourceLinks {
   static class ChangesetLinks {
     private final LinkBuilder changesetLinkBuilder;
 
-    ChangesetLinks(ScmPathInfo uriInfo) {
-      changesetLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, ChangesetRootResource.class);
+    ChangesetLinks(ScmPathInfo pathInfo) {
+      changesetLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, ChangesetRootResource.class);
     }
 
     String self(String namespace, String name, String changesetId) {
@@ -313,8 +311,8 @@ class ResourceLinks {
   static class ModificationsLinks {
     private final LinkBuilder modificationsLinkBuilder;
 
-    ModificationsLinks(ScmPathInfo uriInfo) {
-      modificationsLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, ModificationsRootResource.class);
+    ModificationsLinks(ScmPathInfo pathInfo) {
+      modificationsLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, ModificationsRootResource.class);
     }
     String self(String namespace, String name, String revision) {
       return modificationsLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("modifications").parameters().method("get").parameters(revision).href();
@@ -328,8 +326,8 @@ class ResourceLinks {
   static class FileHistoryLinks {
     private final LinkBuilder fileHistoryLinkBuilder;
 
-    FileHistoryLinks(ScmPathInfo uriInfo) {
-      fileHistoryLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, FileHistoryRootResource.class);
+    FileHistoryLinks(ScmPathInfo pathInfo) {
+      fileHistoryLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, FileHistoryRootResource.class);
     }
 
     String self(String namespace, String name, String changesetId, String path) {
@@ -345,8 +343,8 @@ class ResourceLinks {
   static class SourceLinks {
     private final LinkBuilder sourceLinkBuilder;
 
-    SourceLinks(ScmPathInfo uriInfo) {
-      sourceLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, SourceRootResource.class);
+    SourceLinks(ScmPathInfo pathInfo) {
+      sourceLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, SourceRootResource.class);
     }
 
     String self(String namespace, String name, String revision) {
@@ -378,8 +376,8 @@ class ResourceLinks {
   static class PermissionLinks {
     private final LinkBuilder permissionLinkBuilder;
 
-    PermissionLinks(ScmPathInfo uriInfo) {
-      permissionLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, PermissionRootResource.class);
+    PermissionLinks(ScmPathInfo pathInfo) {
+      permissionLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, PermissionRootResource.class);
     }
 
     String all(String namespace, String name) {
@@ -415,8 +413,8 @@ class ResourceLinks {
   static class UIPluginLinks {
     private final LinkBuilder uiPluginLinkBuilder;
 
-    UIPluginLinks(ScmPathInfo uriInfo) {
-      uiPluginLinkBuilder = new LinkBuilder(uriInfo, UIRootResource.class, UIPluginResource.class);
+    UIPluginLinks(ScmPathInfo pathInfo) {
+      uiPluginLinkBuilder = new LinkBuilder(pathInfo, UIRootResource.class, UIPluginResource.class);
     }
 
     String self(String id) {
@@ -431,8 +429,8 @@ class ResourceLinks {
   static class UIPluginCollectionLinks {
     private final LinkBuilder uiPluginCollectionLinkBuilder;
 
-    UIPluginCollectionLinks(ScmPathInfo uriInfo) {
-      uiPluginCollectionLinkBuilder = new LinkBuilder(uriInfo, UIRootResource.class, UIPluginResource.class);
+    UIPluginCollectionLinks(ScmPathInfo pathInfo) {
+      uiPluginCollectionLinkBuilder = new LinkBuilder(pathInfo, UIRootResource.class, UIPluginResource.class);
     }
 
     String self() {
diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java
index 1ddfb4a3d3..8cb325b818 100644
--- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java
+++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java
@@ -82,7 +82,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
   private final KeyGenerator keyGenerator;
   private final RepositoryDAO repositoryDAO;
   private final Set types;
-  private RepositoryMatcher repositoryMatcher;
   private NamespaceStrategy namespaceStrategy;
   private final ManagerDaoAdapter managerDaoAdapter;
 
@@ -91,12 +90,10 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
   public DefaultRepositoryManager(ScmConfiguration configuration,
                                   SCMContextProvider contextProvider, KeyGenerator keyGenerator,
                                   RepositoryDAO repositoryDAO, Set handlerSet,
-                                  RepositoryMatcher repositoryMatcher,
                                   NamespaceStrategy namespaceStrategy) {
     this.configuration = configuration;
     this.keyGenerator = keyGenerator;
     this.repositoryDAO = repositoryDAO;
-    this.repositoryMatcher = repositoryMatcher;
     this.namespaceStrategy = namespaceStrategy;
 
     ThreadFactory factory = new ThreadFactoryBuilder()
diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java
index 5f4ea2fa72..448c2561f3 100644
--- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java
@@ -54,7 +54,6 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import sonia.scm.SCMContextProvider;
-import sonia.scm.Type;
 import sonia.scm.cache.GuavaCacheManager;
 import sonia.scm.config.ScmConfiguration;
 import sonia.scm.security.AuthorizationCollector;
@@ -120,7 +119,6 @@ public class DefaultRepositoryManagerPerfTest {
       keyGenerator, 
       repositoryDAO,
       handlerSet, 
-      repositoryMatcher,
       namespaceStrategy
     );
     
diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
index d85ce12014..b7d231cf38 100644
--- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
@@ -61,7 +61,6 @@ import sonia.scm.store.ConfigurationStoreFactory;
 import sonia.scm.store.JAXBConfigurationStoreFactory;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.Stack;
@@ -441,7 +440,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase {
     when(namespaceStrategy.createNamespace(Mockito.any(Repository.class))).thenAnswer(invocation -> mockedNamespace);
 
     return new DefaultRepositoryManager(configuration, contextProvider,
-      keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher(), namespaceStrategy);
+      keyGenerator, repositoryDAO, handlerSet, namespaceStrategy);
   }
 
   private void createRepository(RepositoryManager m, Repository repository) throws AlreadyExistsException {
@@ -467,10 +466,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase {
     assertEquals(repo.getLastModified(), other.getLastModified());
   }
 
-  private RepositoryMatcher createRepositoryMatcher() {
-    return new RepositoryMatcher(Collections.emptySet());
-  }
-
   private Repository createRepository(Repository repository) throws AlreadyExistsException {
     manager.create(repository);
     assertNotNull(repository.getId());

From babea160c36ed54b6d9d1ee06e04e20cb7dd8fdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= 
Date: Mon, 17 Sep 2018 17:49:08 +0200
Subject: [PATCH 46/48] Incorporate peer review

---
 .../scm/repository/api/RepositoryService.java | 43 ++++++++++---------
 .../repository/api/ScmProtocolProvider.java   |  4 +-
 .../scm/repository/spi/HttpScmProtocol.java   |  2 +-
 .../InitializingHttpScmProtocolWrapper.java   | 22 +++++-----
 .../web/SvnScmProtocolProviderWrapper.java    |  3 ++
 .../scm/web/protocol/HttpProtocolServlet.java |  6 +--
 .../NamespaceAndNameFromPathExtractor.java    |  7 ++-
 .../RepositoryToRepositoryDtoMapperTest.java  |  2 +-
 .../test/java/sonia/scm/it/GitLfsITCase.java  |  3 +-
 .../sonia/scm/it/RepositoryHookITCase.java    |  6 +--
 .../web/protocol/HttpProtocolServletTest.java | 22 +++-------
 ...NamespaceAndNameFromPathExtractorTest.java |  4 +-
 12 files changed, 58 insertions(+), 66 deletions(-)

diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
index a16001dce3..bdd6e4b320 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
@@ -31,6 +31,7 @@
 
 package sonia.scm.repository.api;
 
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import sonia.scm.cache.CacheManager;
@@ -80,6 +81,7 @@ import java.util.stream.Stream;
  * @apiviz.uses sonia.scm.repository.api.UnbundleCommandBuilder
  * @since 1.17
  */
+@Slf4j
 public final class RepositoryService implements Closeable {
 
   private static final Logger logger = LoggerFactory.getLogger(RepositoryService.class);
@@ -128,7 +130,7 @@ public final class RepositoryService implements Closeable {
     try {
       provider.close();
     } catch (IOException ex) {
-      logger.error("Could not close repository service provider", ex);
+      log.error("Could not close repository service provider", ex);
     }
   }
 
@@ -141,7 +143,7 @@ public final class RepositoryService implements Closeable {
    */
   public BlameCommandBuilder getBlameCommand() {
     logger.debug("create blame command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new BlameCommandBuilder(cacheManager, provider.getBlameCommand(),
       repository, preProcessorUtil);
@@ -156,7 +158,7 @@ public final class RepositoryService implements Closeable {
    */
   public BranchesCommandBuilder getBranchesCommand() {
     logger.debug("create branches command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new BranchesCommandBuilder(cacheManager,
       provider.getBranchesCommand(), repository);
@@ -171,7 +173,7 @@ public final class RepositoryService implements Closeable {
    */
   public BrowseCommandBuilder getBrowseCommand() {
     logger.debug("create browse command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new BrowseCommandBuilder(cacheManager, provider.getBrowseCommand(),
       repository, preProcessorUtil);
@@ -187,7 +189,7 @@ public final class RepositoryService implements Closeable {
    */
   public BundleCommandBuilder getBundleCommand() {
     logger.debug("create bundle command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new BundleCommandBuilder(provider.getBundleCommand(), repository);
   }
@@ -201,7 +203,7 @@ public final class RepositoryService implements Closeable {
    */
   public CatCommandBuilder getCatCommand() {
     logger.debug("create cat command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new CatCommandBuilder(provider.getCatCommand());
   }
@@ -216,7 +218,7 @@ public final class RepositoryService implements Closeable {
    */
   public DiffCommandBuilder getDiffCommand() {
     logger.debug("create diff command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new DiffCommandBuilder(provider.getDiffCommand());
   }
@@ -232,7 +234,7 @@ public final class RepositoryService implements Closeable {
    */
   public IncomingCommandBuilder getIncomingCommand() {
     logger.debug("create incoming command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new IncomingCommandBuilder(cacheManager,
       provider.getIncomingCommand(), repository, preProcessorUtil);
@@ -247,7 +249,7 @@ public final class RepositoryService implements Closeable {
    */
   public LogCommandBuilder getLogCommand() {
     logger.debug("create log command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new LogCommandBuilder(cacheManager, provider.getLogCommand(),
       repository, preProcessorUtil);
@@ -261,7 +263,7 @@ public final class RepositoryService implements Closeable {
    *                                      by the implementation of the repository service provider.
    */
   public ModificationsCommandBuilder getModificationsCommand() {
-    logger.debug("create modifications command for repository {}",repository.getNamespaceAndName());
+    logger.debug("create modifications command for repository {}", repository.getNamespaceAndName());
     return new ModificationsCommandBuilder(provider.getModificationsCommand(),repository, cacheManager.getCache(ModificationsCommandBuilder.CACHE_NAME), preProcessorUtil);
   }
 
@@ -275,7 +277,7 @@ public final class RepositoryService implements Closeable {
    */
   public OutgoingCommandBuilder getOutgoingCommand() {
     logger.debug("create outgoing command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new OutgoingCommandBuilder(cacheManager,
       provider.getOutgoingCommand(), repository, preProcessorUtil);
@@ -291,7 +293,7 @@ public final class RepositoryService implements Closeable {
    */
   public PullCommandBuilder getPullCommand() {
     logger.debug("create pull command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new PullCommandBuilder(provider.getPullCommand(), repository);
   }
@@ -306,7 +308,7 @@ public final class RepositoryService implements Closeable {
    */
   public PushCommandBuilder getPushCommand() {
     logger.debug("create push command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new PushCommandBuilder(provider.getPushCommand());
   }
@@ -329,7 +331,7 @@ public final class RepositoryService implements Closeable {
    */
   public TagsCommandBuilder getTagsCommand() {
     logger.debug("create tags command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new TagsCommandBuilder(cacheManager, provider.getTagsCommand(),
       repository);
@@ -345,7 +347,7 @@ public final class RepositoryService implements Closeable {
    */
   public UnbundleCommandBuilder getUnbundleCommand() {
     logger.debug("create unbundle command for repository {}",
-      repository.getName());
+      repository.getNamespaceAndName());
 
     return new UnbundleCommandBuilder(provider.getUnbundleCommand(),
       repository);
@@ -372,21 +374,20 @@ public final class RepositoryService implements Closeable {
     return provider.getSupportedFeatures().contains(feature);
   }
 
-
-  public Stream getSupportedProtocols() {
+  public  Stream getSupportedProtocols() {
     return protocolProviders.stream()
       .filter(protocolProvider -> protocolProvider.getType().equals(getRepository().getType()))
-      .map(this::createProviderInstanceForRepository);
+      .map(this::createProviderInstanceForRepository);
   }
 
-  private ScmProtocol createProviderInstanceForRepository(ScmProtocolProvider protocolProvider) {
+  private  T createProviderInstanceForRepository(ScmProtocolProvider protocolProvider) {
     return protocolProvider.get(repository);
   }
 
   public  T getProtocol(Class clazz) {
-    return (T) getSupportedProtocols()
+    return this.getSupportedProtocols()
       .filter(scmProtocol -> clazz.isAssignableFrom(scmProtocol.getClass()))
       .findFirst()
-      .orElseThrow(() -> new IllegalArgumentException("no implementation for " + clazz.getName() + " and repository type " + getRepository().getType()));
+      .orElseThrow(() -> new IllegalArgumentException(String.format("no implementation for %s and repository type %s", clazz.getName(),getRepository().getType())));
   }
 }
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java
index d4be5dca59..597826676d 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/ScmProtocolProvider.java
@@ -4,9 +4,9 @@ import sonia.scm.plugin.ExtensionPoint;
 import sonia.scm.repository.Repository;
 
 @ExtensionPoint(multi = true)
-public interface ScmProtocolProvider {
+public interface ScmProtocolProvider {
 
   String getType();
 
-  ScmProtocol get(Repository repository);
+  T get(Repository repository);
 }
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java
index 7ec47ea284..b933abf559 100644
--- a/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/HttpScmProtocol.java
@@ -27,7 +27,7 @@ public abstract class HttpScmProtocol implements ScmProtocol {
 
   @Override
   public String getUrl() {
-      return URI.create(basePath + "/").resolve("repo/" + repository.getNamespace() + "/" + repository.getName()).toASCIIString();
+      return URI.create(basePath + "/").resolve(String.format("repo/%s/%s", repository.getNamespace(), repository.getName())).toASCIIString();
   }
 
   public final void serve(HttpServletRequest request, HttpServletResponse response, ServletConfig config) throws ServletException, IOException {
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
index 57de407edc..c1b7229036 100644
--- a/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/InitializingHttpScmProtocolWrapper.java
@@ -1,7 +1,6 @@
 package sonia.scm.repository.spi;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import lombok.extern.slf4j.Slf4j;
 import sonia.scm.api.v2.resources.ScmPathInfoStore;
 import sonia.scm.config.ScmConfiguration;
 import sonia.scm.repository.Repository;
@@ -18,20 +17,19 @@ import java.util.Optional;
 import static java.util.Optional.empty;
 import static java.util.Optional.of;
 
-public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolProvider {
-
-  private static final Logger logger = LoggerFactory.getLogger(InitializingHttpScmProtocolWrapper.class);
+@Slf4j
+public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolProvider {
 
   private final Provider delegateProvider;
-  private final Provider uriInfoStore;
+  private final Provider pathInfoStore;
   private final ScmConfiguration scmConfiguration;
 
   private volatile boolean isInitialized = false;
 
 
-  protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
+  protected InitializingHttpScmProtocolWrapper(Provider delegateProvider, Provider pathInfoStore, ScmConfiguration scmConfiguration) {
     this.delegateProvider = delegateProvider;
-    this.uriInfoStore = uriInfoStore;
+    this.pathInfoStore = pathInfoStore;
     this.scmConfiguration = scmConfiguration;
   }
 
@@ -42,7 +40,7 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP
   @Override
   public HttpScmProtocol get(Repository repository) {
     if (!repository.getType().equals(getType())) {
-      throw new IllegalArgumentException("cannot handle repository with type " + repository.getType() + " with protocol for type " + getType());
+      throw new IllegalArgumentException(String.format("cannot handle repository with type %s with protocol for type %s", repository.getType(), getType()));
     }
     return new ProtocolWrapper(repository, computeBasePath());
   }
@@ -53,18 +51,18 @@ public abstract class InitializingHttpScmProtocolWrapper implements ScmProtocolP
 
   private Optional getPathFromScmPathInfoIfAvailable() {
     try {
-      ScmPathInfoStore scmPathInfoStore = uriInfoStore.get();
+      ScmPathInfoStore scmPathInfoStore = pathInfoStore.get();
       if (scmPathInfoStore != null && scmPathInfoStore.get() != null) {
         return of(scmPathInfoStore.get().getRootUri().toASCIIString());
       }
     } catch (Exception e) {
-      logger.debug("could not get ScmPathInfoStore from context", e);
+      log.debug("could not get ScmPathInfoStore from context", e);
     }
     return empty();
   }
 
   private String getPathFromConfiguration() {
-    logger.debug("using base path from configuration: {}", scmConfiguration.getBaseUrl());
+    log.debug("using base path from configuration: {}", scmConfiguration.getBaseUrl());
     return scmConfiguration.getBaseUrl();
   }
 
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
index fb7d921742..fb3b948eb9 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
@@ -56,6 +56,9 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr
     }
 
     @Override
+    /**
+     * Overridden to return the systems temp directory for the key {@link PARAMETER_SVN_PARENTPATH}.
+     */
     public String getInitParameter(String key) {
       if (PARAMETER_SVN_PARENTPATH.equals(key)) {
         return System.getProperty("java.io.tmpdir");
diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java
index 2a02afe7f6..bc085d2cc7 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/HttpProtocolServlet.java
@@ -38,15 +38,13 @@ public class HttpProtocolServlet extends HttpServlet {
   private final PushStateDispatcher dispatcher;
   private final UserAgentParser userAgentParser;
 
-  private final NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor;
 
   @Inject
-  public HttpProtocolServlet(RepositoryServiceFactory serviceFactory, Provider requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser, NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor) {
+  public HttpProtocolServlet(RepositoryServiceFactory serviceFactory, Provider requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser) {
     this.serviceFactory = serviceFactory;
     this.requestProvider = requestProvider;
     this.dispatcher = dispatcher;
     this.userAgentParser = userAgentParser;
-    this.namespaceAndNameFromPathExtractor = namespaceAndNameFromPathExtractor;
   }
 
   @Override
@@ -58,7 +56,7 @@ public class HttpProtocolServlet extends HttpServlet {
     } else {
 
       String pathInfo = request.getPathInfo();
-      Optional namespaceAndName = namespaceAndNameFromPathExtractor.fromUri(pathInfo);
+      Optional namespaceAndName = NamespaceAndNameFromPathExtractor.fromUri(pathInfo);
       if (namespaceAndName.isPresent()) {
         service(request, response, namespaceAndName.get());
       } else {
diff --git a/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java
index 8cbdadf942..22e2433561 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractor.java
@@ -8,8 +8,11 @@ import java.util.Optional;
 import static java.util.Optional.empty;
 import static java.util.Optional.of;
 
-class NamespaceAndNameFromPathExtractor {
-  Optional fromUri(String uri) {
+final class NamespaceAndNameFromPathExtractor {
+
+  private NamespaceAndNameFromPathExtractor() {}
+
+  static Optional fromUri(String uri) {
     if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) {
       uri = uri.substring(1);
     }
diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java
index d60b62937e..2e6048d6b8 100644
--- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryToRepositoryDtoMapperTest.java
@@ -42,7 +42,7 @@ public class RepositoryToRepositoryDtoMapperTest {
   private final URI baseUri = URI.create("http://example.com/base/");
   @SuppressWarnings("unused") // Is injected
   private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
-  @Mock//(answer = Answers.RETURNS_DEEP_STUBS)
+  @Mock
   private RepositoryServiceFactory serviceFactory;
   @Mock
   private RepositoryService repositoryService;
diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java
index 611a584485..c55a33c39a 100644
--- a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java
+++ b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java
@@ -251,8 +251,7 @@ public class GitLfsITCase {
   }
 
   private String createBatchUrl() {
-    String url = BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName();
-    return url + "/info/lfs/objects/batch";
+    return String.format("%srepo/%s/%s/info/lfs/objects/batch", BASE_URL, repository.getNamespace(), repository.getName());
   }
 
   private byte[] download(ScmClient client, LfsObject lfsObject) throws IOException {
diff --git a/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java b/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java
index 6ad8342d8a..d74769bf39 100644
--- a/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java
+++ b/scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java
@@ -172,7 +172,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
     Thread.sleep(WAIT_TIME);
     
     // check debug servlet that only one commit is present
-    WebResource.Builder wr = createResource(client, "../debug/" + repository.getNamespace() + "/" + repository.getName() + "/post-receive/last");
+    WebResource.Builder wr = createResource(client, String.format("../debug/%s/%s/post-receive/last", repository.getNamespace(), repository.getName()));
     DebugHookData data = wr.get(DebugHookData.class);
     assertNotNull(data);
     assertThat(data.getChangesets(), allOf(
@@ -195,8 +195,8 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
   
   private RepositoryClient createRepositoryClient() throws IOException 
   {
-    return REPOSITORY_CLIENT_FACTORY.create(repositoryType, 
-      IntegrationTestUtil.BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName(),
+    return REPOSITORY_CLIENT_FACTORY.create(repositoryType,
+      String.format("%srepo/%s/%s", IntegrationTestUtil.BASE_URL, repository.getNamespace(), repository.getName()),
       IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy
     );
   }
diff --git a/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java b/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java
index 2d4f6b639b..077020f60c 100644
--- a/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/web/protocol/HttpProtocolServletTest.java
@@ -20,20 +20,16 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.util.Optional;
 
-import static java.util.Optional.of;
 import static org.mockito.AdditionalMatchers.not;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
 
 public class HttpProtocolServletTest {
 
-  private static final NamespaceAndName EXISTING_REPO = new NamespaceAndName("space", "repo");
 
   @Mock
   private RepositoryServiceFactory serviceFactory;
@@ -44,8 +40,6 @@ public class HttpProtocolServletTest {
   @Mock
   private UserAgentParser userAgentParser;
   @Mock
-  private NamespaceAndNameFromPathExtractor namespaceAndNameFromPathExtractor;
-  @Mock
   private Provider requestProvider;
 
   @InjectMocks
@@ -68,8 +62,9 @@ public class HttpProtocolServletTest {
     initMocks(this);
     when(userAgentParser.parse(request)).thenReturn(userAgent);
     when(userAgent.isBrowser()).thenReturn(false);
-    when(serviceFactory.create(not(eq(EXISTING_REPO)))).thenThrow(RepositoryNotFoundException.class);
-    when(serviceFactory.create(EXISTING_REPO)).thenReturn(repositoryService);
+    NamespaceAndName existingRepo = new NamespaceAndName("space", "repo");
+    when(serviceFactory.create(not(eq(existingRepo)))).thenThrow(RepositoryNotFoundException.class);
+    when(serviceFactory.create(existingRepo)).thenReturn(repositoryService);
     when(requestProvider.get()).thenReturn(httpServletRequest);
   }
 
@@ -85,8 +80,7 @@ public class HttpProtocolServletTest {
 
   @Test
   public void shouldHandleBadPaths() throws IOException, ServletException {
-    when(request.getPathInfo()).thenReturn("/space/name");
-    when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(Optional.empty());
+    when(request.getPathInfo()).thenReturn("/illegal");
 
     servlet.service(request, response);
 
@@ -94,11 +88,8 @@ public class HttpProtocolServletTest {
   }
 
   @Test
-  public void shouldHandleNotExistingRepository() throws RepositoryNotFoundException, IOException, ServletException {
-    when(request.getPathInfo()).thenReturn("/space/name");
-    NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name");
-    when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(of(namespaceAndName));
-    doThrow(new RepositoryNotFoundException(namespaceAndName)).when(serviceFactory).create(namespaceAndName);
+  public void shouldHandleNotExistingRepository() throws IOException, ServletException {
+    when(request.getPathInfo()).thenReturn("/not/exists");
 
     servlet.service(request, response);
 
@@ -109,7 +100,6 @@ public class HttpProtocolServletTest {
   public void shouldDelegateToProvider() throws RepositoryNotFoundException, IOException, ServletException {
     when(request.getPathInfo()).thenReturn("/space/name");
     NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name");
-    when(namespaceAndNameFromPathExtractor.fromUri("/space/name")).thenReturn(of(namespaceAndName));
     doReturn(repositoryService).when(serviceFactory).create(namespaceAndName);
     Repository repository = new Repository();
     when(repositoryService.getRepository()).thenReturn(repository);
diff --git a/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java
index 3018870e7d..0998010069 100644
--- a/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/web/protocol/NamespaceAndNameFromPathExtractorTest.java
@@ -38,7 +38,7 @@ public class NamespaceAndNameFromPathExtractorTest {
     return dynamicTest(
       "should extract correct namespace and name for path " + path,
       () -> {
-        Optional namespaceAndName = new NamespaceAndNameFromPathExtractor().fromUri(path);
+        Optional namespaceAndName = NamespaceAndNameFromPathExtractor.fromUri(path);
 
         assertThat(namespaceAndName.get()).isEqualTo(new NamespaceAndName("space", "repo"));
       }
@@ -59,7 +59,7 @@ public class NamespaceAndNameFromPathExtractorTest {
     return dynamicTest(
       "should not fail for wrong path " + path,
       () -> {
-        Optional namespaceAndName = new NamespaceAndNameFromPathExtractor().fromUri(path);
+        Optional namespaceAndName = NamespaceAndNameFromPathExtractor.fromUri(path);
 
         assertThat(namespaceAndName.isPresent()).isFalse();
       }

From 88506b06339e3c6be3a6143cbc93f9b42b4d4b4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= 
Date: Tue, 18 Sep 2018 08:58:03 +0200
Subject: [PATCH 47/48] Remove unnecessary annotations

---
 .../src/main/java/sonia/scm/web/Git.java           | 14 --------------
 .../scm/web/GitScmProtocolProviderWrapper.java     |  3 +--
 .../main/java/sonia/scm/web/GitServletModule.java  |  3 ---
 .../src/main/java/sonia/scm/web/Hg.java            | 14 --------------
 .../scm/web/HgScmProtocolProviderWrapper.java      |  3 +--
 .../main/java/sonia/scm/web/HgServletModule.java   |  3 ---
 .../src/main/java/sonia/scm/web/Svn.java           | 14 --------------
 .../scm/web/SvnScmProtocolProviderWrapper.java     |  2 +-
 .../main/java/sonia/scm/web/SvnServletModule.java  |  3 ---
 9 files changed, 3 insertions(+), 56 deletions(-)
 delete mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java
 delete mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java
 delete mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java

diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java
deleted file mode 100644
index 8bcf85c8f0..0000000000
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/Git.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package sonia.scm.web;
-
-import com.google.inject.BindingAnnotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@BindingAnnotation
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-@interface Git {
-}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java
index 8273f3950e..be97e7e539 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitScmProtocolProviderWrapper.java
@@ -5,7 +5,6 @@ import sonia.scm.config.ScmConfiguration;
 import sonia.scm.plugin.Extension;
 import sonia.scm.repository.GitRepositoryHandler;
 import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper;
-import sonia.scm.repository.spi.ScmProviderHttpServlet;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -15,7 +14,7 @@ import javax.inject.Singleton;
 @Extension
 public class GitScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper {
   @Inject
-  public GitScmProtocolProviderWrapper(@Git Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
+  public GitScmProtocolProviderWrapper(ScmGitServletProvider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
     super(servletProvider, uriInfoStore, scmConfiguration);
   }
 
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java
index 8c7b30572f..e731e01a62 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java
@@ -41,7 +41,6 @@ import org.mapstruct.factory.Mappers;
 import sonia.scm.api.v2.resources.GitConfigDtoToGitConfigMapper;
 import sonia.scm.api.v2.resources.GitConfigToGitConfigDtoMapper;
 import sonia.scm.plugin.Extension;
-import sonia.scm.repository.spi.ScmProviderHttpServlet;
 import sonia.scm.web.lfs.LfsBlobStoreFactory;
 
 /**
@@ -64,7 +63,5 @@ public class GitServletModule extends ServletModule
 
     bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass());
     bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass());
-
-    bind(ScmProviderHttpServlet.class).annotatedWith(Git.class).toProvider(ScmGitServletProvider.class);
   }
 }
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java
deleted file mode 100644
index e4fe39e724..0000000000
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/Hg.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package sonia.scm.web;
-
-import com.google.inject.BindingAnnotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@BindingAnnotation
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-@interface Hg {
-}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java
index 72382f16bc..37360a5845 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgScmProtocolProviderWrapper.java
@@ -5,7 +5,6 @@ import sonia.scm.config.ScmConfiguration;
 import sonia.scm.plugin.Extension;
 import sonia.scm.repository.HgRepositoryHandler;
 import sonia.scm.repository.spi.InitializingHttpScmProtocolWrapper;
-import sonia.scm.repository.spi.ScmProviderHttpServlet;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -15,7 +14,7 @@ import javax.inject.Singleton;
 @Extension
 public class HgScmProtocolProviderWrapper extends InitializingHttpScmProtocolWrapper {
   @Inject
-  public HgScmProtocolProviderWrapper(@Hg Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
+  public HgScmProtocolProviderWrapper(HgCGIServletProvider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
     super(servletProvider, uriInfoStore, scmConfiguration);
   }
 
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java
index 6949be2ea9..ba9ae3a0b9 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java
@@ -46,7 +46,6 @@ import sonia.scm.plugin.Extension;
 import sonia.scm.repository.HgContext;
 import sonia.scm.repository.HgContextProvider;
 import sonia.scm.repository.HgHookManager;
-import sonia.scm.repository.spi.ScmProviderHttpServlet;
 
 /**
  *
@@ -80,8 +79,6 @@ public class HgServletModule extends ServletModule
     bind(HgConfigPackagesToDtoMapper.class).to(Mappers.getMapper(HgConfigPackagesToDtoMapper.class).getClass());
     bind(HgConfigInstallationsToDtoMapper.class);
 
-    bind(ScmProviderHttpServlet.class).annotatedWith(Hg.class).toProvider(HgCGIServletProvider.class);
-
     // bind servlets
     serve(MAPPING_HOOK).with(HgHookCallbackServlet.class);
   }
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java
deleted file mode 100644
index 744c1a0939..0000000000
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/Svn.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package sonia.scm.web;
-
-import com.google.inject.BindingAnnotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@BindingAnnotation
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-@interface Svn {
-}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
index fb3b948eb9..ba7d5e875a 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnScmProtocolProviderWrapper.java
@@ -27,7 +27,7 @@ public class SvnScmProtocolProviderWrapper extends InitializingHttpScmProtocolWr
   }
 
   @Inject
-  public SvnScmProtocolProviderWrapper(@Svn Provider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
+  public SvnScmProtocolProviderWrapper(SvnDAVServletProvider servletProvider, Provider uriInfoStore, ScmConfiguration scmConfiguration) {
     super(servletProvider, uriInfoStore, scmConfiguration);
   }
 
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java
index cd47a2fa44..8526d6380a 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java
@@ -38,7 +38,6 @@ import org.mapstruct.factory.Mappers;
 import sonia.scm.api.v2.resources.SvnConfigDtoToSvnConfigMapper;
 import sonia.scm.api.v2.resources.SvnConfigToSvnConfigDtoMapper;
 import sonia.scm.plugin.Extension;
-import sonia.scm.repository.spi.ScmProviderHttpServlet;
 
 /**
  *
@@ -51,7 +50,5 @@ public class SvnServletModule extends ServletModule {
   protected void configureServlets() {
     bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass());
     bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass());
-
-    bind(ScmProviderHttpServlet.class).annotatedWith(Svn.class).toProvider(SvnDAVServletProvider.class);
   }
 }

From 039d752b493d53ace427a008075d4f063780e87c Mon Sep 17 00:00:00 2001
From: Mohamed Karray 
Date: Tue, 18 Sep 2018 07:44:51 +0000
Subject: [PATCH 48/48] Close branch feature/repository_protocol_v2