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 */