diff --git a/assembly/assembly-wsmaster-war/pom.xml b/assembly/assembly-wsmaster-war/pom.xml
index 503c89825c7..8d121c3eccb 100644
--- a/assembly/assembly-wsmaster-war/pom.xml
+++ b/assembly/assembly-wsmaster-war/pom.xml
@@ -139,6 +139,10 @@
org.eclipse.che.core
che-core-api-factory-bitbucket-server
+
+ org.eclipse.che.core
+ che-core-api-factory-git-ssh
+
org.eclipse.che.core
che-core-api-factory-github
diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
index 274c1ff2f82..93379d7a999 100644
--- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
+++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
@@ -36,6 +36,7 @@
import org.eclipse.che.api.factory.server.FactoryCreateValidator;
import org.eclipse.che.api.factory.server.FactoryEditValidator;
import org.eclipse.che.api.factory.server.FactoryParametersResolver;
+import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
import org.eclipse.che.api.factory.server.ScmFileResolver;
import org.eclipse.che.api.factory.server.ScmService;
import org.eclipse.che.api.factory.server.azure.devops.AzureDevOpsFactoryParametersResolver;
@@ -44,6 +45,8 @@
import org.eclipse.che.api.factory.server.bitbucket.BitbucketScmFileResolver;
import org.eclipse.che.api.factory.server.bitbucket.BitbucketServerAuthorizingFactoryParametersResolver;
import org.eclipse.che.api.factory.server.bitbucket.BitbucketServerScmFileResolver;
+import org.eclipse.che.api.factory.server.git.ssh.GitSshFactoryParametersResolver;
+import org.eclipse.che.api.factory.server.git.ssh.GitSshScmFileResolver;
import org.eclipse.che.api.factory.server.github.GithubFactoryParametersResolver;
import org.eclipse.che.api.factory.server.github.GithubScmFileResolver;
import org.eclipse.che.api.factory.server.gitlab.GitlabFactoryParametersResolver;
@@ -175,6 +178,10 @@ protected void configure() {
factoryParametersResolverMultibinder
.addBinding()
.to(AzureDevOpsFactoryParametersResolver.class);
+ factoryParametersResolverMultibinder
+ .addBinding()
+ .to(RawDevfileUrlFactoryParameterResolver.class);
+ factoryParametersResolverMultibinder.addBinding().to(GitSshFactoryParametersResolver.class);
Multibinder scmFileResolverResolverMultibinder =
Multibinder.newSetBinder(binder(), ScmFileResolver.class);
@@ -183,6 +190,7 @@ protected void configure() {
scmFileResolverResolverMultibinder.addBinding().to(GitlabScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(BitbucketServerScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(AzureDevOpsScmFileResolver.class);
+ scmFileResolverResolverMultibinder.addBinding().to(GitSshScmFileResolver.class);
install(new org.eclipse.che.api.factory.server.scm.KubernetesScmModule());
install(new org.eclipse.che.api.factory.server.bitbucket.BitbucketServerModule());
diff --git a/core/che-core-db/src/test/java/org/eclipse/che/core/db/TracingDataSourceTest.java b/core/che-core-db/src/test/java/org/eclipse/che/core/db/TracingDataSourceTest.java
index 4d62c462376..b6f7ebc5d30 100644
--- a/core/che-core-db/src/test/java/org/eclipse/che/core/db/TracingDataSourceTest.java
+++ b/core/che-core-db/src/test/java/org/eclipse/che/core/db/TracingDataSourceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2021 Red Hat, Inc.
+ * Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
@@ -77,7 +77,7 @@ public void shouldBeAbleTogetTracingDataSource() throws Exception {
}
@Test
- public void shouldNotWrapDatasourceIfEnvSetToFalseØ() throws Exception {
+ public void shouldNotWrapDatasourceIfEnvSetToFalse() throws Exception {
setEnv(ImmutableMap.of("CHE_DB_TRACING_ENABLED", "false"));
DataSource actual = TracingDataSource.wrapWithTracingIfEnabled(dataSource);
diff --git a/pom.xml b/pom.xml
index a3327d661f8..b6386b7de55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -759,6 +759,11 @@
che-core-api-factory-bitbucket-server
${che.version}
+
+ org.eclipse.che.core
+ che-core-api-factory-git-ssh
+ ${che.version}
+
org.eclipse.che.core
che-core-api-factory-github
diff --git a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsFactoryParametersResolver.java b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsFactoryParametersResolver.java
index 065beb994c0..e98e35d7e63 100644
--- a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsFactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsFactoryParametersResolver.java
@@ -23,7 +23,7 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
-import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.ProjectConfigDtoMerger;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
@@ -45,11 +45,13 @@
* @author Anatolii Bazko
*/
@Singleton
-public class AzureDevOpsFactoryParametersResolver extends RawDevfileUrlFactoryParameterResolver {
+public class AzureDevOpsFactoryParametersResolver implements FactoryParametersResolver {
/** Parser which will allow to check validity of URLs and create objects. */
private final AzureDevOpsURLParser azureDevOpsURLParser;
+ private final URLFetcher urlFetcher;
+ private final URLFactoryBuilder urlFactoryBuilder;
private final PersonalAccessTokenManager personalAccessTokenManager;
private final ProjectConfigDtoMerger projectConfigDtoMerger;
@@ -60,8 +62,9 @@ public AzureDevOpsFactoryParametersResolver(
URLFetcher urlFetcher,
URLFactoryBuilder urlFactoryBuilder,
PersonalAccessTokenManager personalAccessTokenManager) {
- super(urlFactoryBuilder, urlFetcher);
this.azureDevOpsURLParser = azureDevOpsURLParser;
+ this.urlFetcher = urlFetcher;
+ this.urlFactoryBuilder = urlFactoryBuilder;
this.personalAccessTokenManager = personalAccessTokenManager;
this.projectConfigDtoMerger = projectConfigDtoMerger;
}
diff --git a/wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerAuthorizingFactoryParametersResolver.java b/wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerAuthorizingFactoryParametersResolver.java
index b055d51d707..7aafa4baec8 100644
--- a/wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerAuthorizingFactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerAuthorizingFactoryParametersResolver.java
@@ -22,7 +22,7 @@
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
@@ -43,8 +43,10 @@
*/
@Singleton
public class BitbucketServerAuthorizingFactoryParametersResolver
- extends RawDevfileUrlFactoryParameterResolver {
+ implements FactoryParametersResolver {
+ private final URLFactoryBuilder urlFactoryBuilder;
+ private final URLFetcher urlFetcher;
/** Parser which will allow to check validity of URLs and create objects. */
private final BitbucketServerURLParser bitbucketURLParser;
@@ -56,7 +58,8 @@ public BitbucketServerAuthorizingFactoryParametersResolver(
URLFetcher urlFetcher,
BitbucketServerURLParser bitbucketURLParser,
PersonalAccessTokenManager personalAccessTokenManager) {
- super(urlFactoryBuilder, urlFetcher);
+ this.urlFactoryBuilder = urlFactoryBuilder;
+ this.urlFetcher = urlFetcher;
this.bitbucketURLParser = bitbucketURLParser;
this.personalAccessTokenManager = personalAccessTokenManager;
}
diff --git a/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketAuthorizingFileContentProvider.java b/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketAuthorizingFileContentProvider.java
index 66e03c8bcdd..bdee138fcc9 100644
--- a/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketAuthorizingFileContentProvider.java
+++ b/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketAuthorizingFileContentProvider.java
@@ -61,7 +61,7 @@ public String fetchContent(String fileURL) throws IOException, DevfileException
requestURL.substring(requestURL.indexOf(split[6]) + split[6].length() + 1),
token.getToken());
} catch (UnknownScmProviderException e) {
- return fetchContentWithoutToken(requestURL, e);
+ return fetchContentWithoutToken(requestURL);
} catch (ScmCommunicationException e) {
return toIOException(fileURL, e);
} catch (ScmUnauthorizedException
diff --git a/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketFactoryParametersResolver.java b/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketFactoryParametersResolver.java
index 75631a9624a..86b37a7cb01 100644
--- a/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketFactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketFactoryParametersResolver.java
@@ -22,7 +22,7 @@
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.ProjectConfigDtoMerger;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
@@ -38,14 +38,16 @@
/** Provides Factory Parameters resolver for bitbucket repositories. */
@Singleton
-public class BitbucketFactoryParametersResolver extends RawDevfileUrlFactoryParameterResolver {
+public class BitbucketFactoryParametersResolver implements FactoryParametersResolver {
/** Parser which will allow to check validity of URLs and create objects. */
private final BitbucketURLParser bitbucketURLParser;
+ private final URLFetcher urlFetcher;
/** Builder allowing to build objects from bitbucket URL. */
private final BitbucketSourceStorageBuilder bitbucketSourceStorageBuilder;
+ private final URLFactoryBuilder urlFactoryBuilder;
/** ProjectDtoMerger */
private final ProjectConfigDtoMerger projectConfigDtoMerger;
@@ -63,9 +65,10 @@ public BitbucketFactoryParametersResolver(
ProjectConfigDtoMerger projectConfigDtoMerger,
PersonalAccessTokenManager personalAccessTokenManager,
BitbucketApiClient bitbucketApiClient) {
- super(urlFactoryBuilder, urlFetcher);
this.bitbucketURLParser = bitbucketURLParser;
+ this.urlFetcher = urlFetcher;
this.bitbucketSourceStorageBuilder = bitbucketSourceStorageBuilder;
+ this.urlFactoryBuilder = urlFactoryBuilder;
this.projectConfigDtoMerger = projectConfigDtoMerger;
this.personalAccessTokenManager = personalAccessTokenManager;
this.bitbucketApiClient = bitbucketApiClient;
diff --git a/wsmaster/che-core-api-factory-git-ssh/pom.xml b/wsmaster/che-core-api-factory-git-ssh/pom.xml
new file mode 100644
index 00000000000..b99ad198159
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/pom.xml
@@ -0,0 +1,112 @@
+
+
+
+ 4.0.0
+
+ che-master-parent
+ org.eclipse.che.core
+ 7.75.0-SNAPSHOT
+
+ che-core-api-factory-git-ssh
+ jar
+ Che Core :: API :: Factory Resolver Git Ssh
+
+ true
+
+
+
+ jakarta.inject
+ jakarta.inject-api
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ org.eclipse.che.core
+ che-core-api-core
+
+
+ org.eclipse.che.core
+ che-core-api-dto
+
+
+ org.eclipse.che.core
+ che-core-api-factory
+
+
+ org.eclipse.che.core
+ che-core-api-factory-shared
+
+
+ org.eclipse.che.core
+ che-core-api-workspace
+
+
+ org.eclipse.che.core
+ che-core-api-workspace-shared
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+ com.github.tomakehurst
+ wiremock-jre8-standalone
+ test
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ test
+
+
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+ test
+
+
+ org.eclipse.che.core
+ che-core-commons-json
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockito
+ mockito-testng
+ test
+
+
+ org.slf4j
+ jcl-over-slf4j
+ test
+
+
+ org.testng
+ testng
+ test
+
+
+
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshAuthorizingFileContentProvider.java b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshAuthorizingFileContentProvider.java
new file mode 100644
index 00000000000..094a2a2575b
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshAuthorizingFileContentProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import org.eclipse.che.api.factory.server.scm.AuthorizingFileContentProvider;
+import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
+import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
+
+/**
+ * Git Ssh specific authorizing file content provider.
+ *
+ * @author Anatolii Bazko
+ */
+class GitSshAuthorizingFileContentProvider extends AuthorizingFileContentProvider {
+
+ GitSshAuthorizingFileContentProvider(
+ GitSshUrl gitSshUrl,
+ URLFetcher urlFetcher,
+ PersonalAccessTokenManager personalAccessTokenManager) {
+ super(gitSshUrl, urlFetcher, personalAccessTokenManager);
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshFactoryParametersResolver.java b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshFactoryParametersResolver.java
new file mode 100644
index 00000000000..685976aef1d
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshFactoryParametersResolver.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import static org.eclipse.che.api.factory.server.FactoryResolverPriority.LOWEST;
+import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
+import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
+import static org.eclipse.che.dto.server.DtoFactory.newDto;
+
+import jakarta.validation.constraints.NotNull;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.che.api.core.ApiException;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
+import org.eclipse.che.api.factory.server.FactoryResolverPriority;
+import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
+import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
+import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
+import org.eclipse.che.api.factory.shared.dto.FactoryDevfileV2Dto;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
+import org.eclipse.che.api.factory.shared.dto.FactoryMetaDto;
+import org.eclipse.che.api.factory.shared.dto.FactoryVisitor;
+import org.eclipse.che.api.factory.shared.dto.ScmInfoDto;
+import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
+import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto;
+import org.eclipse.che.api.workspace.shared.dto.devfile.SourceDto;
+
+/**
+ * Provides Factory Parameters resolver for Git Ssh repositories.
+ *
+ * @author Anatolii Bazko
+ */
+@Singleton
+public class GitSshFactoryParametersResolver implements FactoryParametersResolver {
+
+ private final GitSshURLParser gitSshURLParser;
+
+ private final URLFetcher urlFetcher;
+ private final URLFactoryBuilder urlFactoryBuilder;
+ private final PersonalAccessTokenManager personalAccessTokenManager;
+
+ @Inject
+ public GitSshFactoryParametersResolver(
+ GitSshURLParser gitSshURLParser,
+ URLFetcher urlFetcher,
+ URLFactoryBuilder urlFactoryBuilder,
+ PersonalAccessTokenManager personalAccessTokenManager) {
+ this.gitSshURLParser = gitSshURLParser;
+ this.urlFetcher = urlFetcher;
+ this.urlFactoryBuilder = urlFactoryBuilder;
+ this.personalAccessTokenManager = personalAccessTokenManager;
+ }
+
+ @Override
+ public boolean accept(@NotNull final Map factoryParameters) {
+ return factoryParameters.containsKey(URL_PARAMETER_NAME)
+ && gitSshURLParser.isValid(factoryParameters.get(URL_PARAMETER_NAME));
+ }
+
+ @Override
+ public FactoryMetaDto createFactory(@NotNull final Map factoryParameters)
+ throws ApiException {
+ // no need to check null value of url parameter as accept() method has performed the check
+ final GitSshUrl gitSshUrl = gitSshURLParser.parse(factoryParameters.get(URL_PARAMETER_NAME));
+
+ // create factory from the following location if location exists, else create default factory
+ return urlFactoryBuilder
+ .createFactoryFromDevfile(
+ gitSshUrl,
+ new GitSshAuthorizingFileContentProvider(
+ gitSshUrl, urlFetcher, personalAccessTokenManager),
+ extractOverrideParams(factoryParameters),
+ true)
+ .orElseGet(() -> newDto(FactoryDto.class).withV(CURRENT_VERSION).withSource("repo"))
+ .acceptVisitor(new GitSshFactoryVisitor(gitSshUrl));
+ }
+
+ /**
+ * Visitor that puts the default devfile or updates devfile projects into the Git Ssh Factory, if
+ * needed.
+ */
+ private class GitSshFactoryVisitor implements FactoryVisitor {
+
+ private final GitSshUrl gitSshUrl;
+
+ private GitSshFactoryVisitor(GitSshUrl gitSshUrl) {
+ this.gitSshUrl = gitSshUrl;
+ }
+
+ @Override
+ public FactoryDevfileV2Dto visit(FactoryDevfileV2Dto factoryDto) {
+ ScmInfoDto scmInfo =
+ newDto(ScmInfoDto.class)
+ .withScmProviderName(gitSshUrl.getProviderName())
+ .withRepositoryUrl(gitSshUrl.getRepositoryLocation());
+ return factoryDto.withScmInfo(scmInfo);
+ }
+
+ @Override
+ public FactoryDto visit(FactoryDto factory) {
+ if (factory.getDevfile() == null) {
+ factory.setDevfile(urlFactoryBuilder.buildDefaultDevfile(gitSshUrl.getRepository()));
+ }
+
+ updateProjects(
+ factory.getDevfile(),
+ () ->
+ newDto(ProjectDto.class)
+ .withSource(
+ newDto(SourceDto.class)
+ .withLocation(gitSshUrl.getRepositoryLocation())
+ .withType("git"))
+ .withName(gitSshUrl.getRepository()),
+ project -> {});
+
+ return factory;
+ }
+ }
+
+ @Override
+ public RemoteFactoryUrl parseFactoryUrl(String factoryUrl) {
+ return gitSshURLParser.parse(factoryUrl);
+ }
+
+ @Override
+ public FactoryResolverPriority priority() {
+ return LOWEST;
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshScmFileResolver.java b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshScmFileResolver.java
new file mode 100644
index 00000000000..a28b208cb89
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshScmFileResolver.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import jakarta.validation.constraints.NotNull;
+import javax.inject.Inject;
+import org.eclipse.che.api.factory.server.ScmFileResolver;
+
+/**
+ * Git Ssh specific SCM file resolver.
+ *
+ * @author Anatolii Bazko
+ */
+public class GitSshScmFileResolver implements ScmFileResolver {
+
+ private final GitSshURLParser gitSshURLParser;
+
+ @Inject
+ public GitSshScmFileResolver(GitSshURLParser gitSshURLParser) {
+ this.gitSshURLParser = gitSshURLParser;
+ }
+
+ @Override
+ public boolean accept(@NotNull String repository) {
+ return gitSshURLParser.isValid(repository);
+ }
+
+ /**
+ * There is no way to get a file content from a git repository via ssh protocol. So this method
+ * always returns an empty string. It allows to start a workspace from an empty devfile.
+ */
+ @Override
+ public String fileContent(@NotNull String repository, @NotNull String filePath) {
+ return "";
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParser.java b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParser.java
new file mode 100644
index 00000000000..9c25e825b72
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParser.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import static java.lang.String.format;
+import static java.util.regex.Pattern.compile;
+
+import jakarta.validation.constraints.NotNull;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
+
+/**
+ * Parser of String Git Ssh URLs and provide {@link GitSshUrl} objects.
+ *
+ * @author Anatolii Bazko
+ */
+@Singleton
+public class GitSshURLParser {
+
+ private final Pattern gitSshPattern;
+
+ private final DevfileFilenamesProvider devfileFilenamesProvider;
+
+ @Inject
+ public GitSshURLParser(DevfileFilenamesProvider devfileFilenamesProvider) {
+ this.devfileFilenamesProvider = devfileFilenamesProvider;
+ this.gitSshPattern = compile("^git@(?[^:]++):(.*)/(?[^/]++)$");
+ }
+
+ public boolean isValid(@NotNull String url) {
+ return gitSshPattern.matcher(url).matches();
+ }
+
+ public GitSshUrl parse(String url) {
+ Matcher matcher = gitSshPattern.matcher(url);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(
+ format("The given url %s is not a valid. It should start with git@", url));
+ }
+
+ String hostName = matcher.group("hostName");
+ String repoName = matcher.group("repoName");
+ if (repoName.endsWith(".git")) {
+ repoName = repoName.substring(0, repoName.length() - 4);
+ }
+
+ return new GitSshUrl()
+ .withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames())
+ .withHostName(hostName)
+ .withRepository(repoName)
+ .withRepositoryLocation(url)
+ .withUrl(url);
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshUrl.java b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshUrl.java
new file mode 100644
index 00000000000..ae180c9e07b
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshUrl.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.eclipse.che.api.factory.server.urlfactory.DefaultFactoryUrl;
+
+/**
+ * Representation of Git Ssh URL, allowing to get details from it.
+ *
+ * @author Anatolii Bazko
+ */
+public class GitSshUrl extends DefaultFactoryUrl {
+
+ private String repository;
+ private String hostName;
+
+ private String repositoryLocation;
+
+ private final List devfileFilenames = new ArrayList<>();
+
+ protected GitSshUrl() {}
+
+ @Override
+ public String getProviderName() {
+ return "git-ssh";
+ }
+
+ @Override
+ public String getBranch() {
+ return null;
+ }
+
+ public GitSshUrl withDevfileFilenames(List devfileFilenames) {
+ this.devfileFilenames.addAll(devfileFilenames);
+ return this;
+ }
+
+ @Override
+ public void setDevfileFilename(String devfileName) {
+ this.devfileFilenames.clear();
+ this.devfileFilenames.add(devfileName);
+ }
+
+ @Override
+ public List devfileFileLocations() {
+ return devfileFilenames.stream().map(this::createDevfileLocation).collect(Collectors.toList());
+ }
+
+ @Override
+ public String rawFileLocation(String filename) {
+ return filename;
+ }
+
+ private DevfileLocation createDevfileLocation(String devfileFilename) {
+ return new DevfileLocation() {
+ @Override
+ public Optional filename() {
+ return Optional.of(devfileFilename);
+ }
+
+ @Override
+ public String location() {
+ return devfileFilename;
+ }
+ };
+ }
+
+ @Override
+ public String getHostName() {
+ return hostName;
+ }
+
+ public GitSshUrl withHostName(String hostName) {
+ this.hostName = hostName;
+ return this;
+ }
+
+ public String getRepositoryLocation() {
+ return repositoryLocation;
+ }
+
+ public GitSshUrl withRepositoryLocation(String repositoryLocation) {
+ this.repositoryLocation = repositoryLocation;
+ return this;
+ }
+
+ public String getRepository() {
+ return repository;
+ }
+
+ public GitSshUrl withRepository(String repository) {
+ this.repository = repository;
+ return this;
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/test/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParserTest.java b/wsmaster/che-core-api-factory-git-ssh/src/test/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParserTest.java
new file mode 100644
index 00000000000..715e5f544b0
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/test/java/org/eclipse/che/api/factory/server/git/ssh/GitSshURLParserTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server.git.ssh;
+
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+
+import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/** @author Anatalii Bazko */
+@Listeners(MockitoTestNGListener.class)
+public class GitSshURLParserTest {
+
+ private GitSshURLParser gitSshURLParser;
+
+ @BeforeMethod
+ protected void start() {
+ gitSshURLParser = new GitSshURLParser(mock(DevfileFilenamesProvider.class));
+ }
+
+ @Test(dataProvider = "parsing")
+ public void testParse(String url, String hostName, String repository) {
+ GitSshUrl gitSshUrl = gitSshURLParser.parse(url);
+
+ assertEquals(gitSshUrl.getHostName(), hostName);
+ assertEquals(gitSshUrl.getRepository(), repository);
+ }
+
+ @DataProvider(name = "parsing")
+ public Object[][] expectedParsing() {
+ return new Object[][] {
+ {"git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepo", "ssh.dev.azure.com", "MyRepo"},
+ {"git@github.com:MyOrg/MyRepo.git", "github.com", "MyRepo"},
+ };
+ }
+}
diff --git a/wsmaster/che-core-api-factory-git-ssh/src/test/resources/logback-test.xml b/wsmaster/che-core-api-factory-git-ssh/src/test/resources/logback-test.xml
new file mode 100644
index 00000000000..704cbbf50f4
--- /dev/null
+++ b/wsmaster/che-core-api-factory-git-ssh/src/test/resources/logback-test.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ %-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n%nopex
+
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java
index 477e8ce5426..4c96fd82446 100644
--- a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java
@@ -19,11 +19,10 @@
import jakarta.validation.constraints.NotNull;
import java.util.Map;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.ProjectConfigDtoMerger;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
@@ -36,7 +35,6 @@
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto;
-import org.eclipse.che.commons.annotation.Nullable;
/**
* Provides Factory Parameters resolver for github repositories.
@@ -44,14 +42,18 @@
* @author Florent Benoit
*/
@Singleton
-public class GithubFactoryParametersResolver extends RawDevfileUrlFactoryParameterResolver {
+public class GithubFactoryParametersResolver implements FactoryParametersResolver {
/** Parser which will allow to check validity of URLs and create objects. */
private final GithubURLParser githubUrlParser;
+ private final URLFetcher urlFetcher;
+
/** Builder allowing to build objects from github URL. */
private final GithubSourceStorageBuilder githubSourceStorageBuilder;
+ private final URLFactoryBuilder urlFactoryBuilder;
+
/** ProjectDtoMerger */
private final ProjectConfigDtoMerger projectConfigDtoMerger;
@@ -59,32 +61,16 @@ public class GithubFactoryParametersResolver extends RawDevfileUrlFactoryParamet
@Inject
public GithubFactoryParametersResolver(
- GithubURLParser githubUrlParser,
- URLFetcher urlFetcher,
- GithubSourceStorageBuilder githubSourceStorageBuilder,
- URLFactoryBuilder urlFactoryBuilder,
- ProjectConfigDtoMerger projectConfigDtoMerger,
- PersonalAccessTokenManager personalAccessTokenManager,
- @Nullable @Named("che.integration.github.oauth_endpoint") String oauthEndpoint) {
- this(
- githubUrlParser,
- urlFetcher,
- githubSourceStorageBuilder,
- urlFactoryBuilder,
- projectConfigDtoMerger,
- personalAccessTokenManager);
- }
-
- GithubFactoryParametersResolver(
GithubURLParser githubUrlParser,
URLFetcher urlFetcher,
GithubSourceStorageBuilder githubSourceStorageBuilder,
URLFactoryBuilder urlFactoryBuilder,
ProjectConfigDtoMerger projectConfigDtoMerger,
PersonalAccessTokenManager personalAccessTokenManager) {
- super(urlFactoryBuilder, urlFetcher);
this.githubUrlParser = githubUrlParser;
+ this.urlFetcher = urlFetcher;
this.githubSourceStorageBuilder = githubSourceStorageBuilder;
+ this.urlFactoryBuilder = urlFactoryBuilder;
this.projectConfigDtoMerger = projectConfigDtoMerger;
this.personalAccessTokenManager = personalAccessTokenManager;
}
diff --git a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolver.java b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolver.java
index cdbf4a02048..efedf3f1eef 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolver.java
@@ -22,7 +22,7 @@
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
+import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
@@ -41,8 +41,10 @@
* @author Max Shaposhnyk
*/
@Singleton
-public class GitlabFactoryParametersResolver extends RawDevfileUrlFactoryParameterResolver {
+public class GitlabFactoryParametersResolver implements FactoryParametersResolver {
+ private final URLFactoryBuilder urlFactoryBuilder;
+ private final URLFetcher urlFetcher;
private final GitlabUrlParser gitlabURLParser;
private final PersonalAccessTokenManager personalAccessTokenManager;
@@ -52,7 +54,8 @@ public GitlabFactoryParametersResolver(
URLFetcher urlFetcher,
GitlabUrlParser gitlabURLParser,
PersonalAccessTokenManager personalAccessTokenManager) {
- super(urlFactoryBuilder, urlFetcher);
+ this.urlFactoryBuilder = urlFactoryBuilder;
+ this.urlFetcher = urlFetcher;
this.gitlabURLParser = gitlabURLParser;
this.personalAccessTokenManager = personalAccessTokenManager;
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
index 617b0758519..d29e982e437 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
@@ -11,12 +11,20 @@
*/
package org.eclipse.che.api.factory.server;
+import static java.util.stream.Collectors.toMap;
+
import jakarta.validation.constraints.NotNull;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
import org.eclipse.che.api.factory.shared.dto.FactoryMetaDto;
+import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto;
+import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto;
/**
* Defines a resolver that will produce factories for some parameters
@@ -24,7 +32,6 @@
* @author Florent Benoit
*/
public interface FactoryParametersResolver {
-
/**
* Resolver acceptance based on the given parameters.
*
@@ -50,4 +57,46 @@ public interface FactoryParametersResolver {
* @throws ApiException when authentication required operations fail
*/
RemoteFactoryUrl parseFactoryUrl(String factoryUrl) throws ApiException;
+
+ /**
+ * Returns priority of the resolver. Resolvers with higher priority will be used among matched
+ * resolvers.
+ */
+ default FactoryResolverPriority priority() {
+ return FactoryResolverPriority.DEFAULT;
+ }
+
+ /**
+ * Finds and returns devfile override parameters in general factory parameters map.
+ *
+ * @param factoryParameters map containing factory data parameters provided through URL
+ * @return filtered devfile values override map
+ */
+ default Map extractOverrideParams(Map factoryParameters) {
+ String overridePrefix = "override.";
+ return factoryParameters.entrySet().stream()
+ .filter(e -> e.getKey().startsWith(overridePrefix))
+ .collect(toMap(e -> e.getKey().substring(overridePrefix.length()), Map.Entry::getValue));
+ }
+
+ /**
+ * If devfile has no projects, put there one provided by given `projectSupplier`. Otherwise update
+ * all projects with given `projectModifier`.
+ *
+ * @param devfile of the projects to update
+ * @param projectSupplier provides default project
+ * @param projectModifier updates existing projects
+ */
+ default void updateProjects(
+ DevfileDto devfile,
+ Supplier projectSupplier,
+ Consumer projectModifier) {
+ List projects = devfile.getProjects();
+ if (projects.isEmpty()) {
+ devfile.setProjects(Collections.singletonList(projectSupplier.get()));
+ } else {
+ // update existing project with same repository, set current branch if needed
+ projects.forEach(projectModifier);
+ }
+ }
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryResolverPriority.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryResolverPriority.java
new file mode 100644
index 00000000000..abbc82a57e2
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryResolverPriority.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.factory.server;
+
+public enum FactoryResolverPriority {
+ DEFAULT(1),
+ HIGHEST(2),
+ LOWEST(0);
+
+ private final int value;
+
+ FactoryResolverPriority(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
index 580e42f4af5..6a5b030d3ae 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
@@ -13,6 +13,7 @@
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import static java.util.Collections.singletonMap;
+import static java.util.Comparator.comparingInt;
import static org.eclipse.che.api.factory.server.ApiExceptionMapper.toApiException;
import static org.eclipse.che.api.factory.server.FactoryLinksHelper.createLinks;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
@@ -28,6 +29,7 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import org.eclipse.che.api.core.ApiException;
@@ -175,8 +177,6 @@ protected static class FactoryParametersResolverHolder {
@SuppressWarnings("unused")
private Set specificFactoryParametersResolvers;
- @Inject private RawDevfileUrlFactoryParameterResolver defaultFactoryResolver;
-
/**
* Provides a suitable resolver for the given parameters. If there is no at least one resolver
* able to process parameters,then {@link BadRequestException} will be thrown
@@ -185,20 +185,19 @@ protected static class FactoryParametersResolverHolder {
*/
public FactoryParametersResolver getFactoryParametersResolver(Map parameters)
throws BadRequestException {
- // Check if the URL is a raw devfile URL. If so, use the default resolver,
- // which resolves factories from a direct URL to a devfile content.
- if (defaultFactoryResolver.accept(parameters)) {
- return defaultFactoryResolver;
- }
- for (FactoryParametersResolver factoryParametersResolver :
- specificFactoryParametersResolvers) {
- try {
- if (factoryParametersResolver.accept(parameters)) {
- return factoryParametersResolver;
- }
- } catch (IllegalArgumentException e) {
- // ignore and try next resolver
- }
+ Optional resolverOptional =
+ specificFactoryParametersResolvers.stream()
+ .filter(
+ r -> {
+ try {
+ return r.accept(parameters);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ })
+ .max(comparingInt(r -> r.priority().getValue()));
+ if (resolverOptional.isPresent()) {
+ return resolverOptional.get();
}
throw new BadRequestException(FACTORY_NOT_RESOLVABLE);
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/RawDevfileUrlFactoryParameterResolver.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/RawDevfileUrlFactoryParameterResolver.java
index 2c87847d6ab..50e5147cbe8 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/RawDevfileUrlFactoryParameterResolver.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/RawDevfileUrlFactoryParameterResolver.java
@@ -13,7 +13,7 @@
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
-import static java.util.stream.Collectors.toMap;
+import static org.eclipse.che.api.factory.server.FactoryResolverPriority.HIGHEST;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
import jakarta.validation.constraints.NotNull;
@@ -21,14 +21,8 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
import javax.inject.Inject;
-import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.factory.server.urlfactory.DefaultFactoryUrl;
@@ -37,18 +31,13 @@
import org.eclipse.che.api.factory.shared.dto.FactoryMetaDto;
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
import org.eclipse.che.api.workspace.server.devfile.URLFileContentProvider;
-import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto;
-import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto;
/**
* {@link FactoryParametersResolver} implementation to resolve factory based on url parameter as a
* direct URL to a devfile content. Extracts and applies devfile values override parameters.
*/
-@Singleton
public class RawDevfileUrlFactoryParameterResolver implements FactoryParametersResolver {
- private static final String OVERRIDE_PREFIX = "override.";
-
protected final URLFactoryBuilder urlFactoryBuilder;
protected final URLFetcher urlFetcher;
@@ -109,36 +98,8 @@ public RemoteFactoryUrl parseFactoryUrl(String factoryUrl) throws ApiException {
throw new ApiException("Operation is not supported");
}
- /**
- * Finds and returns devfile override parameters in general factory parameters map.
- *
- * @param factoryParameters map containing factory data parameters provided through URL
- * @return filtered devfile values override map
- */
- protected Map extractOverrideParams(Map factoryParameters) {
- return factoryParameters.entrySet().stream()
- .filter(e -> e.getKey().startsWith(OVERRIDE_PREFIX))
- .collect(toMap(e -> e.getKey().substring(OVERRIDE_PREFIX.length()), Entry::getValue));
- }
-
- /**
- * If devfile has no projects, put there one provided by given `projectSupplier`. Otherwise update
- * all projects with given `projectModifier`.
- *
- * @param devfile of the projects to update
- * @param projectSupplier provides default project
- * @param projectModifier updates existing projects
- */
- protected void updateProjects(
- DevfileDto devfile,
- Supplier projectSupplier,
- Consumer projectModifier) {
- List projects = devfile.getProjects();
- if (projects.isEmpty()) {
- devfile.setProjects(Collections.singletonList(projectSupplier.get()));
- } else {
- // update existing project with same repository, set current branch if needed
- projects.forEach(projectModifier);
- }
+ @Override
+ public FactoryResolverPriority priority() {
+ return HIGHEST;
}
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/scm/AuthorizingFileContentProvider.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/scm/AuthorizingFileContentProvider.java
index 3cae6931813..1bb4fbcfa19 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/scm/AuthorizingFileContentProvider.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/scm/AuthorizingFileContentProvider.java
@@ -92,7 +92,7 @@ private String fetchContent(
return urlFetcher.fetch(requestURL, authorization);
}
} catch (UnknownScmProviderException e) {
- return fetchContentWithoutToken(requestURL, e);
+ return fetchContentWithoutToken(requestURL);
} catch (ScmCommunicationException e) {
return toIOException(fileURL, e);
} catch (ScmUnauthorizedException
@@ -102,7 +102,7 @@ private String fetchContent(
}
}
- protected String fetchContentWithoutToken(String requestURL, UnknownScmProviderException e)
+ protected String fetchContentWithoutToken(String requestURL)
throws DevfileException, IOException {
// we don't have any provider matching this SCM provider
// so try without secrets being configured
@@ -123,7 +123,7 @@ protected String fetchContentWithoutToken(String requestURL, UnknownScmProviderE
}
}
throw new DevfileException(
- String.format("%s: %s", e.getMessage(), exception.getMessage()), exception);
+ "Could not reach devfile at " + "`" + exception.getMessage() + "`", exception);
}
}
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
index 77157764afd..44046b990f8 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
@@ -15,6 +15,9 @@
import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
import static java.lang.String.valueOf;
import static java.util.Collections.singletonMap;
+import static org.eclipse.che.api.factory.server.FactoryResolverPriority.DEFAULT;
+import static org.eclipse.che.api.factory.server.FactoryResolverPriority.HIGHEST;
+import static org.eclipse.che.api.factory.server.FactoryResolverPriority.LOWEST;
import static org.eclipse.che.api.factory.server.FactoryService.VALIDATE_QUERY_PARAMETER;
import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
@@ -35,40 +38,27 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
-import java.io.IOException;
-import java.util.ArrayList;
+import java.lang.reflect.Field;
import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.model.user.User;
-import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
-import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.core.rest.ApiExceptionMapper;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
import org.eclipse.che.api.factory.server.FactoryService.FactoryParametersResolverHolder;
import org.eclipse.che.api.factory.server.builder.FactoryBuilder;
import org.eclipse.che.api.factory.server.impl.SourceStorageParametersValidator;
-import org.eclipse.che.api.factory.server.model.impl.AuthorImpl;
-import org.eclipse.che.api.factory.server.model.impl.FactoryImpl;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.user.server.PreferenceManager;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
-import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
-import org.eclipse.che.api.workspace.server.model.impl.MachineConfigImpl;
-import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
-import org.eclipse.che.api.workspace.server.model.impl.RecipeImpl;
-import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
-import org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl;
-import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
-import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.dto.server.DtoFactory;
@@ -111,6 +101,7 @@ public class FactoryServiceTest {
@Mock private PersonalAccessTokenManager personalAccessTokenManager;
@InjectMocks private FactoryParametersResolverHolder factoryParametersResolverHolder;
+ private Set specificFactoryParametersResolvers;
private FactoryBuilder factoryBuilderSpy;
@@ -126,6 +117,13 @@ public class FactoryServiceTest {
@BeforeMethod
public void setUp() throws Exception {
+ specificFactoryParametersResolvers = new HashSet<>();
+ Field parametersResolvers =
+ FactoryParametersResolverHolder.class.getDeclaredField(
+ "specificFactoryParametersResolvers");
+ parametersResolvers.setAccessible(true);
+ parametersResolvers.set(factoryParametersResolverHolder, specificFactoryParametersResolvers);
+ specificFactoryParametersResolvers.add(rawDevfileUrlFactoryParameterResolver);
factoryBuilderSpy = spy(new FactoryBuilder(new SourceStorageParametersValidator()));
lenient().doNothing().when(factoryBuilderSpy).checkValid(any(FactoryDto.class));
lenient().doNothing().when(factoryBuilderSpy).checkValid(any(FactoryDto.class), anyBoolean());
@@ -284,62 +282,71 @@ public void shouldReturnDefaultFactoryParameterResolver() throws Exception {
.startsWith(RawDevfileUrlFactoryParameterResolver.class.getName()));
}
- private FactoryImpl createFactory() {
- return createNamedFactory(FACTORY_NAME);
- }
+ @Test
+ public void shouldReturnTopPriorityFactoryParameterResolverOverLowPriority() throws Exception {
+ // given
+ Map params = singletonMap(URL_PARAMETER_NAME, "https://host/path/devfile.yaml");
+ specificFactoryParametersResolvers.clear();
+ FactoryParametersResolver topPriorityResolver = mock(FactoryParametersResolver.class);
+ FactoryParametersResolver lowPriorityResolver = mock(FactoryParametersResolver.class);
+ when(topPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(lowPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(topPriorityResolver.priority()).thenReturn(HIGHEST);
+ when(lowPriorityResolver.priority()).thenReturn(LOWEST);
+ specificFactoryParametersResolvers.add(topPriorityResolver);
+ specificFactoryParametersResolvers.add(lowPriorityResolver);
- private FactoryImpl createNamedFactory(String name) {
- return createFactoryWithStorage(name, PROJECT_SOURCE_TYPE, PROJECT_SOURCE_LOCATION);
- }
+ // when
+ FactoryParametersResolver factoryParametersResolver =
+ factoryParametersResolverHolder.getFactoryParametersResolver(params);
- private FactoryImpl createFactoryWithStorage(String name, String type, String location) {
- return FactoryImpl.builder()
- .setId(FACTORY_ID)
- .setVersion("4.0")
- .setWorkspace(createWorkspaceConfig(type, location))
- .setCreator(new AuthorImpl(USER_ID, 12L))
- .setName(name)
- .build();
+ // then
+ assertEquals(factoryParametersResolver, topPriorityResolver);
}
- private static WorkspaceConfig createWorkspaceConfig(String type, String location) {
- return WorkspaceConfigImpl.builder()
- .setName(WORKSPACE_NAME)
- .setEnvironments(singletonMap("env1", new EnvironmentImpl(createEnvDto())))
- .setProjects(createProjects(type, location))
- .build();
- }
+ @Test
+ public void shouldReturnTopPriorityFactoryParameterResolverOverDefaultPriority()
+ throws Exception {
+ // given
+ Map params = singletonMap(URL_PARAMETER_NAME, "https://host/path/devfile.yaml");
+ specificFactoryParametersResolvers.clear();
+ FactoryParametersResolver topPriorityResolver = mock(FactoryParametersResolver.class);
+ FactoryParametersResolver defaultPriorityResolver = mock(FactoryParametersResolver.class);
+ when(topPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(defaultPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(topPriorityResolver.priority()).thenReturn(HIGHEST);
+ when(defaultPriorityResolver.priority()).thenReturn(DEFAULT);
+ specificFactoryParametersResolvers.add(topPriorityResolver);
+ specificFactoryParametersResolvers.add(defaultPriorityResolver);
- private static EnvironmentDto createEnvDto() {
- final RecipeImpl environmentRecipe = new RecipeImpl();
- environmentRecipe.setType("type");
- environmentRecipe.setContent("content");
- environmentRecipe.setContentType("compose");
- environmentRecipe.setLocation("location");
- final EnvironmentImpl env = new EnvironmentImpl();
- final MachineConfigImpl extendedMachine = new MachineConfigImpl();
- extendedMachine.setAttributes(singletonMap("att1", "value"));
- extendedMachine.setServers(
- singletonMap(
- "agent", new ServerConfigImpl("5555", "https", "path", singletonMap("key", "value"))));
- env.setRecipe(environmentRecipe);
- env.setMachines(singletonMap("machine1", extendedMachine));
- return org.eclipse.che.api.workspace.server.DtoConverter.asDto(env);
- }
+ // when
+ FactoryParametersResolver factoryParametersResolver =
+ factoryParametersResolverHolder.getFactoryParametersResolver(params);
- private static List createProjects(String type, String location) {
- final ProjectConfigImpl projectConfig = new ProjectConfigImpl();
- projectConfig.setSource(new SourceStorageImpl(type, location, null));
- return ImmutableList.of(projectConfig);
+ // then
+ assertEquals(factoryParametersResolver, topPriorityResolver);
}
- private static T getFromResponse(Response response, Class clazz) throws Exception {
- return DTO.createDtoFromJson(response.getBody().asInputStream(), clazz);
- }
+ @Test
+ public void shouldReturnDefaultPriorityFactoryParameterResolverOverLowPriority()
+ throws Exception {
+ // given
+ Map params = singletonMap(URL_PARAMETER_NAME, "https://host/path/devfile.yaml");
+ specificFactoryParametersResolvers.clear();
+ FactoryParametersResolver lowPriorityResolver = mock(FactoryParametersResolver.class);
+ FactoryParametersResolver defaultPriorityResolver = mock(FactoryParametersResolver.class);
+ when(lowPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(defaultPriorityResolver.accept(eq(params))).thenReturn(true);
+ when(lowPriorityResolver.priority()).thenReturn(LOWEST);
+ when(defaultPriorityResolver.priority()).thenReturn(DEFAULT);
+ specificFactoryParametersResolvers.add(lowPriorityResolver);
+ specificFactoryParametersResolvers.add(defaultPriorityResolver);
+
+ // when
+ FactoryParametersResolver factoryParametersResolver =
+ factoryParametersResolverHolder.getFactoryParametersResolver(params);
- private static List unwrapDtoList(Response response, Class dtoClass)
- throws IOException {
- return new ArrayList<>(
- DtoFactory.getInstance().createListDtoFromJson(response.body().asInputStream(), dtoClass));
+ // then
+ assertEquals(factoryParametersResolver, defaultPriorityResolver);
}
}
diff --git a/wsmaster/pom.xml b/wsmaster/pom.xml
index 8ebb3cb90f4..2eaf61d8d1c 100644
--- a/wsmaster/pom.xml
+++ b/wsmaster/pom.xml
@@ -40,6 +40,7 @@
che-core-api-account
che-core-api-user
che-core-api-factory-azure-devops
+ che-core-api-factory-git-ssh
che-core-api-factory-shared
che-core-api-factory
che-core-api-factory-github