diff --git a/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryHttpClient.java b/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryHttpClient.java deleted file mode 100644 index 936280802..000000000 --- a/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryHttpClient.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2011 JFrog Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jfrog.build.client; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; -import org.apache.commons.codec.net.URLCodec; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.util.EntityUtils; -import org.jfrog.build.api.util.Log; -import org.jfrog.build.util.URI; - -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -import static org.apache.commons.codec.binary.StringUtils.getBytesUtf8; -import static org.apache.commons.codec.binary.StringUtils.newStringUsAscii; - -/** - * @author Noam Y. Tenne - */ -public class ArtifactoryHttpClient implements AutoCloseable { - - public static final ArtifactoryVersion UNKNOWN_PROPERTIES_TOLERANT_ARTIFACTORY_VERSION = - new ArtifactoryVersion("2.2.3"); - public static final ArtifactoryVersion NON_NUMERIC_BUILD_NUMBERS_TOLERANT_ARTIFACTORY_VERSION = - new ArtifactoryVersion("2.2.4"); - public static final ArtifactoryVersion STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION = - new ArtifactoryVersion("5.2.1"); - public static final ArtifactoryVersion MINIMAL_ARTIFACTORY_VERSION = new ArtifactoryVersion("2.2.3"); - public static final String VERSION_INFO_URL = "/api/system/version"; - private static final int DEFAULT_CONNECTION_TIMEOUT_SECS = 300; // 5 Minutes in seconds - public static final int DEFAULT_CONNECTION_RETRY = 3; - private final Log log; - private final String artifactoryUrl; - private final String username; - private final String password; - private final String accessToken; - private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT_SECS; - private int connectionRetries = DEFAULT_CONNECTION_RETRY; - private ProxyConfiguration proxyConfiguration; - private boolean insecureTls = false; - private SSLContext sslContext; - - private PreemptiveHttpClient deployClient; - - private ArtifactoryHttpClient(String artifactoryUrl, String username, String password, String accessToken, Log log) { - this.artifactoryUrl = StringUtils.stripEnd(artifactoryUrl, "/"); - this.username = username; - this.password = password; - this.accessToken = accessToken; - this.log = log; - } - - public ArtifactoryHttpClient(String artifactoryUrl, String username, String password, Log log) { - this(artifactoryUrl, username, password, StringUtils.EMPTY, log); - } - - public ArtifactoryHttpClient(String artifactoryUrl, String accessToken, Log log) { - this(artifactoryUrl, StringUtils.EMPTY, StringUtils.EMPTY, accessToken, log); - } - - public static String encodeUrl(String unescaped) { - byte[] rawData = URLCodec.encodeUrl(URI.allowed_query, getBytesUtf8(unescaped)); - return newStringUsAscii(rawData); - } - - /** - * Sets the proxy host and port. - * - * @param host Proxy host - * @param port Proxy port - */ - public void setProxyConfiguration(String host, int port) { - setProxyConfiguration(host, port, null, null); - } - - /** - * Sets the proxy details. - * - * @param host Proxy host - * @param port Proxy port - * @param username Username to authenticate with the proxy - * @param password Password to authenticate with the proxy - */ - public void setProxyConfiguration(String host, int port, String username, String password) { - proxyConfiguration = new ProxyConfiguration(); - proxyConfiguration.host = host; - proxyConfiguration.port = port; - proxyConfiguration.username = username; - proxyConfiguration.password = password; - } - - /** - * Network timeout in seconds to use both for connection establishment and for unanswered requests. - * - * @param connectionTimeout Timeout in seconds. - */ - public void setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - /** - * Max Retries to perform - * - * @param connectionRetries The number of max retries. - */ - public void setConnectionRetries(int connectionRetries) { - this.connectionRetries = connectionRetries; - } - - public void setInsecureTls(boolean insecureTls) { - this.insecureTls = insecureTls; - } - - public void setSslContext(SSLContext sslContext) { - this.sslContext = sslContext; - } - - public int getConnectionRetries() { - return connectionRetries; - } - - public ProxyConfiguration getProxyConfiguration() { - return this.proxyConfiguration; - } - - /** - * Release all connection and cleanup resources. - */ - @Override - public void close() { - if (deployClient != null) { - deployClient.close(); - } - } - - public PreemptiveHttpClient getHttpClient() { - return getHttpClient(connectionTimeout); - } - - public PreemptiveHttpClient getHttpClient(int connectionTimeout) { - if (deployClient == null) { - PreemptiveHttpClientBuilder clientBuilder = new PreemptiveHttpClientBuilder() - .setConnectionRetries(connectionRetries) - .setInsecureTls(insecureTls) - .setTimeout(connectionTimeout) - .setSslContext(sslContext) - .setLog(log); - if (proxyConfiguration != null) { - clientBuilder.setProxyConfiguration(proxyConfiguration); - } - if (StringUtils.isNotEmpty(accessToken)) { - clientBuilder.setAccessToken(accessToken); - } else { - clientBuilder.setUserName(username).setPassword(password); - } - deployClient = clientBuilder.build(); - } - - return deployClient; - } - - public ArtifactoryVersion getVersion() throws IOException { - String versionUrl = artifactoryUrl + VERSION_INFO_URL; - try (CloseableHttpResponse response = executeGetRequest(versionUrl)) { - HttpEntity httpEntity = response.getEntity(); - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode == HttpStatus.SC_NOT_FOUND) { - EntityUtils.consumeQuietly(httpEntity); - return ArtifactoryVersion.NOT_FOUND; - } - if (statusCode != HttpStatus.SC_OK) { - String message = getMessageFromEntity(httpEntity); - EntityUtils.consumeQuietly(httpEntity); - throw new IOException(message); - } - if (httpEntity == null) { - return ArtifactoryVersion.NOT_FOUND; - } - try (InputStream content = httpEntity.getContent()) { - JsonNode result = getJsonNode(content); - log.debug("Version result: " + result); - String version = result.get("version").asText(); - JsonNode addonsNode = result.get("addons"); - boolean hasAddons = (addonsNode != null) && addonsNode.iterator().hasNext(); - return new ArtifactoryVersion(version, hasAddons); - } - } - } - - public JsonNode getJsonNode(InputStream content) throws IOException { - JsonParser parser = createJsonParser(content); - return parser.readValueAsTree(); - } - - private CloseableHttpResponse executeGetRequest(String lastModifiedUrl) throws IOException { - PreemptiveHttpClient client = getHttpClient(); - HttpGet httpGet = new HttpGet(lastModifiedUrl); - return client.execute(httpGet); - } - - public JsonParser createJsonParser(InputStream in) throws IOException { - JsonFactory jsonFactory = createJsonFactory(); - return jsonFactory.createParser(in); - } - - public JsonParser createJsonParser(String content) throws IOException { - JsonFactory jsonFactory = createJsonFactory(); - return jsonFactory.createParser(content); - } - - public JsonFactory createJsonFactory() { - JsonFactory jsonFactory = new JsonFactory(); - ObjectMapper mapper = new ObjectMapper(jsonFactory); - mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector()); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - jsonFactory.setCodec(mapper); - return jsonFactory; - } - - public ArtifactoryUploadResponse upload(HttpPut httpPut, HttpEntity fileEntity) throws IOException { - httpPut.setEntity(fileEntity); - return execute(httpPut); - } - - public ArtifactoryUploadResponse execute(HttpPut httpPut) throws IOException { - ArtifactoryUploadResponse artifactoryResponse = new ArtifactoryUploadResponse(); - try (CloseableHttpResponse response = getHttpClient().execute(httpPut)) { - artifactoryResponse.setStatusLine(response.getStatusLine()); - if (response.getEntity() == null || response.getEntity().getContent() == null) { - return artifactoryResponse; - } - try (InputStream in = response.getEntity().getContent()) { - String content = IOUtils.toString(in, StandardCharsets.UTF_8.name()); - if (StringUtils.isEmpty(content)) { - return artifactoryResponse; - } - try { - JsonParser parser = createJsonParser(content); - artifactoryResponse = parser.readValueAs(ArtifactoryUploadResponse.class); - artifactoryResponse.setStatusLine(response.getStatusLine()); - } catch (Exception e) { - // Displays the response received from the client and the stacktrace in case an Exception caught. - log.info("Response received: \n\n" + content + "\n\n"); - log.error("Failed while reading the response from: " + httpPut, e); - } - } - return artifactoryResponse; - } - } - - /** - * @param entity the entity to retrieve the message from. - * @return response entity content. - * @throws IOException if entity couldn't serialize - */ - - public String getMessageFromEntity(HttpEntity entity) throws IOException { - String responseMessage = ""; - if (entity != null) { - responseMessage = getResponseEntityContent(entity); - if (StringUtils.isNotBlank(responseMessage)) { - responseMessage = " Response message: " + responseMessage; - } - } - return responseMessage; - } - - /** - * Returns the response entity content - * - * @param responseEntity the response entity - * @return response entity content - * @throws IOException - */ - private String getResponseEntityContent(HttpEntity responseEntity) throws IOException { - InputStream in = responseEntity.getContent(); - if (in != null) { - return IOUtils.toString(in, StandardCharsets.UTF_8.name()); - } - return ""; - } -} diff --git a/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryVersion.java b/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryVersion.java index 7ef2f9221..e889f1951 100644 --- a/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryVersion.java +++ b/build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryVersion.java @@ -16,4 +16,8 @@ public ArtifactoryVersion(String version, boolean addons) { public boolean hasAddons() { return addons; } + + public boolean isOSS(){ + return !hasAddons(); + } } diff --git a/build-info-client/src/main/java/org/jfrog/build/client/JFrogHttpClient.java b/build-info-client/src/main/java/org/jfrog/build/client/JFrogHttpClient.java new file mode 100644 index 000000000..ab9311d9e --- /dev/null +++ b/build-info-client/src/main/java/org/jfrog/build/client/JFrogHttpClient.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 JFrog Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jfrog.build.client; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URI; + +/** + * @author Noam Y. Tenne + */ +public class JFrogHttpClient implements AutoCloseable { + + public static final ArtifactoryVersion STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION = + new ArtifactoryVersion("5.2.1"); + private static final int DEFAULT_CONNECTION_TIMEOUT_SECS = 300; // 5 Minutes in seconds + public static final int DEFAULT_CONNECTION_RETRY = 3; + private final String url; + private final PreemptiveHttpClientBuilder clientBuilder; + + private PreemptiveHttpClient deployClient; + private Log log; + + private JFrogHttpClient(String url, String username, String password, String accessToken, Log log) { + this.url = StringUtils.removeEnd(url, "/"); + this.log = log; + clientBuilder = new PreemptiveHttpClientBuilder() + .setConnectionRetries(DEFAULT_CONNECTION_RETRY) + .setInsecureTls(false) + .setTimeout(DEFAULT_CONNECTION_TIMEOUT_SECS) + .setLog(log); + if (StringUtils.isNotEmpty(accessToken)) { + clientBuilder.setAccessToken(accessToken); + } else { + clientBuilder.setUserName(username).setPassword(password); + } + } + + public JFrogHttpClient(String artifactoryUrl, String username, String password, Log log) { + this(artifactoryUrl, username, password, StringUtils.EMPTY, log); + } + + public JFrogHttpClient(String artifactoryUrl, String accessToken, Log log) { + this(artifactoryUrl, StringUtils.EMPTY, StringUtils.EMPTY, accessToken, log); + } + + /** + * Sets the proxy host and port. + * + * @param host Proxy host + * @param port Proxy port + */ + public void setProxyConfiguration(String host, int port) { + setProxyConfiguration(host, port, null, null); + } + + /** + * Sets the proxy details. + * + * @param host Proxy host + * @param port Proxy port + * @param username Username to authenticate with the proxy + * @param password Password to authenticate with the proxy + */ + public void setProxyConfiguration(String host, int port, String username, String password) { + ProxyConfiguration proxyConfiguration = new ProxyConfiguration(); + proxyConfiguration.host = host; + proxyConfiguration.port = port; + proxyConfiguration.username = username; + proxyConfiguration.password = password; + clientBuilder.setProxyConfiguration(proxyConfiguration); + } + + /** + * Network timeout in seconds to use both for connection establishment and for unanswered requests. + * + * @param connectionTimeout Timeout in seconds. + */ + public void setConnectionTimeout(int connectionTimeout) { + clientBuilder.setTimeout(connectionTimeout); + } + + public void setInsecureTls(boolean insecureTls) { + clientBuilder.setInsecureTls(insecureTls); + } + + public void setSslContext(SSLContext sslContext) { + clientBuilder.setSslContext(sslContext); + } + + public int getConnectionRetries() { + return clientBuilder.connectionRetries; + } + + /** + * Max Retries to perform + * + * @param connectionRetries The number of max retries. + */ + public void setConnectionRetries(int connectionRetries) { + clientBuilder.setConnectionRetries(connectionRetries); + } + + public ProxyConfiguration getProxyConfiguration() { + return clientBuilder.getProxyConfiguration(); + } + + /** + * Release all connection and cleanup resources. + */ + @Override + public void close() { + if (deployClient != null) { + deployClient.close(); + } + } + + public PreemptiveHttpClient getHttpClient() { + if (deployClient == null) { + deployClient = clientBuilder.build(); + } + return deployClient; + } + + public CloseableHttpResponse sendRequest(HttpRequestBase request) throws IOException { + log.debug("Base URL: " + request.getURI().toString()); + PreemptiveHttpClient client = getHttpClient(); + String url = request.getURI().toString(); + request.setURI(URI.create((this.url + "/" + StringUtils.removeStart(url, "/")))); + return client.execute(request); + } + + public Log getLog() { + return log; + } + + public void setLog(Log log) { + this.log = log; + } + + public String getUrl() { + return url; + } + +} diff --git a/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClient.java b/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClient.java index 2956f6bde..482f153d3 100644 --- a/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClient.java +++ b/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClient.java @@ -68,7 +68,7 @@ public PreemptiveHttpClient(PoolingHttpClientConnectionManager connectionManager this.connectionRetries = connectionRetries; this.log = log; - int retryCount = connectionRetries < 0 ? ArtifactoryHttpClient.DEFAULT_CONNECTION_RETRY : connectionRetries; + int retryCount = connectionRetries < 0 ? JFrogHttpClient.DEFAULT_CONNECTION_RETRY : connectionRetries; clientBuilder.setRetryHandler(new PreemptiveHttpClient.PreemptiveRetryHandler(retryCount)); clientBuilder.setServiceUnavailableRetryStrategy(new PreemptiveHttpClient.PreemptiveRetryStrategy()); clientBuilder.setRedirectStrategy(new PreemptiveHttpClient.PreemptiveRedirectStrategy()); diff --git a/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClientBuilder.java b/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClientBuilder.java index 9dac6ecb1..9dcb0aa75 100644 --- a/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClientBuilder.java +++ b/build-info-client/src/main/java/org/jfrog/build/client/PreemptiveHttpClientBuilder.java @@ -103,7 +103,9 @@ public PreemptiveHttpClientBuilder setProxyConfiguration(ProxyConfiguration prox } return this; } - + public ProxyConfiguration getProxyConfiguration(){ + return proxyConfiguration; + } public PreemptiveHttpClientBuilder setConnectionRetries(int connectionRetries) { this.connectionRetries = connectionRetries; return this; diff --git a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/DockerUtils.java b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/DockerUtils.java index 8b865b08c..0497e3504 100644 --- a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/DockerUtils.java +++ b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/DockerUtils.java @@ -5,15 +5,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.codec.binary.Hex; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -223,17 +218,6 @@ public static int getNumberOfDependentLayers(String imageContent) throws IOExcep return layersNum; } - /** - * Converts the http entity to string. If entity is null, returns empty string. - */ - public static String entityToString(HttpEntity entity) throws IOException { - if (entity != null) { - InputStream is = entity.getContent(); - return IOUtils.toString(is, StandardCharsets.UTF_8.name()); - } - return ""; - } - /** * Layer file name to digest format. */ @@ -278,13 +262,11 @@ public static Boolean isImageVersioned(String imageTag) { * @param repo - Repository from which to download the layer * @param imageName - Image name to download * @param imageDigests - image digest to download - * @param dependenciesClient - Dependencies client + * @param artifactoryManager - Artifactory Manager */ - public static void downloadMarkerLayer(String repo, String imageName, String imageDigests, ArtifactoryDependenciesClient dependenciesClient) throws IOException { - String url = dependenciesClient.getArtifactoryUrl() + "/api/docker/" + repo + "/v2/" + imageName + "/blobs/" + imageDigests; - try (CloseableHttpResponse response = dependenciesClient.getArtifactMetadata(url)) { - EntityUtils.consume(response.getEntity()); - } + public static void downloadMarkerLayer(String repo, String imageName, String imageDigests, ArtifactoryManager artifactoryManager) throws IOException { + String url = "/api/docker/" + repo + "/v2/" + imageName + "/blobs/" + imageDigests; + artifactoryManager.downloadHeaders(url); } /** diff --git a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerCommand.java b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerCommand.java index 794a4d41f..8c194ddde 100644 --- a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerCommand.java +++ b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerCommand.java @@ -2,8 +2,7 @@ import org.jfrog.build.api.Module; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.packageManager.PackageManagerExtractor; import java.util.ArrayList; @@ -11,8 +10,7 @@ import java.util.Map; abstract class DockerCommand extends PackageManagerExtractor { - ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; - ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; + ArtifactoryManagerBuilder artifactoryManagerBuilder; Map env; String username; String password; @@ -32,10 +30,9 @@ abstract class DockerCommand extends PackageManagerExtractor { * @param logger - log output. * @param env - Environment variables to use during docker push execution. */ - public DockerCommand(ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, + public DockerCommand(ArtifactoryManagerBuilder artifactoryManagerBuilder, String imageTag, String host, String targetRepository, String username, String password, Log logger, Map env) { - this.dependenciesClientBuilder = dependenciesClientBuilder; - this.buildInfoClientBuilder = buildInfoClientBuilder; + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.targetRepository = targetRepository; this.logger = logger; this.imageTag = imageTag; @@ -44,5 +41,4 @@ public DockerCommand(ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, A this.password = password; this.env = env; } - } diff --git a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPull.java b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPull.java index 01f641af2..5215bf256 100644 --- a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPull.java +++ b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPull.java @@ -6,9 +6,8 @@ import org.jfrog.build.api.Build; import org.jfrog.build.api.Module; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.docker.DockerJavaWrapper; import org.jfrog.build.extractor.docker.DockerUtils; import org.jfrog.build.extractor.docker.types.DockerImage; @@ -29,9 +28,9 @@ public class DockerPull extends DockerCommand { * @param logger - log output. * @param env - Environment variables to use during docker push execution. */ - public DockerPull(ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, + public DockerPull(ArtifactoryManagerBuilder artifactoryManagerBuilder, String imageTag, String host, String targetRepository, String username, String password, Log logger, Map env) { - super(buildInfoClientBuilder, dependenciesClientBuilder, imageTag, host, targetRepository, username, password, logger, env); + super(artifactoryManagerBuilder, imageTag, host, targetRepository, username, password, logger, env); } /** @@ -43,12 +42,11 @@ public static void main(String[] ignored) { try { // Client builders. ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); - ArtifactoryDependenciesClientBuilder dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); - ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); + ArtifactoryManagerBuilder artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); // Load artifact and BuildInfo properties from resolver section in the BuildInfo.properties file. ArtifactoryClientConfiguration.DockerHandler dockerHandler = clientConfiguration.dockerHandler; // Init DockerPull. - DockerPull dockerPush = new DockerPull(buildInfoClientBuilder, dependenciesClientBuilder, + DockerPull dockerPush = new DockerPull(artifactoryManagerBuilder, dockerHandler.getImageTag(), dockerHandler.getHost(), clientConfiguration.resolver.getRepoKey(), @@ -76,7 +74,7 @@ public Build execute() { DockerJavaWrapper.pullImage(imageTag, username, password, host, env, logger); String imageId = DockerJavaWrapper.getImageIdFromTag(imageTag, host, env, logger); Pair archDetails = DockerJavaWrapper.getImageArch(imageTag, host, env, logger); - DockerImage image = new DockerImage(imageId, imageTag, targetRepository, buildInfoClientBuilder, dependenciesClientBuilder, archDetails.getLeft(), archDetails.getRight()); + DockerImage image = new DockerImage(imageId, imageTag, targetRepository, artifactoryManagerBuilder, archDetails.getLeft(), archDetails.getRight()); Module module = image.generateBuildInfoModule(logger, DockerUtils.CommandType.Pull); if (module.getDependencies() == null || module.getDependencies().size() == 0) { logger.warn("Could not find docker image: " + imageTag + " in Artifactory."); diff --git a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPush.java b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPush.java index 6d6f001ef..1ed24c141 100644 --- a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPush.java +++ b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/extractor/DockerPush.java @@ -3,17 +3,12 @@ import com.google.common.collect.ArrayListMultimap; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; import org.jfrog.build.api.Build; import org.jfrog.build.api.Module; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.docker.DockerJavaWrapper; import org.jfrog.build.extractor.docker.DockerUtils; import org.jfrog.build.extractor.docker.types.DockerImage; @@ -23,7 +18,6 @@ import java.io.IOException; import java.util.Map; -import static org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils.buildMatrixParamsString; import static org.jfrog.build.extractor.packageManager.PackageManagerUtils.createArtifactoryClientConfiguration; public class DockerPush extends DockerCommand { @@ -31,8 +25,7 @@ public class DockerPush extends DockerCommand { /** - * @param buildInfoClientBuilder - Build Info client builder. - * @param dependenciesClientBuilder - Dependencies client builder. + * @param artifactoryManagerBuilder - Artifactory manager builder. * @param targetRepository - The repository it'll deploy to. * @param imageTag - Image tag to push. * @param logger - The logger. @@ -42,10 +35,10 @@ public class DockerPush extends DockerCommand { * @param artifactProperties - Properties to be attached to the docker layers deployed to Artifactory. * @param env - Environment variables to use during docker push execution. */ - public DockerPush(ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, + public DockerPush(ArtifactoryManagerBuilder artifactoryManagerBuilder, String imageTag, String host, ArrayListMultimap artifactProperties, String targetRepository, String username, String password, Log logger, Map env) { - super(buildInfoClientBuilder, dependenciesClientBuilder, imageTag, host, targetRepository, username, password, logger, env); + super(artifactoryManagerBuilder, imageTag, host, targetRepository, username, password, logger, env); this.artifactProperties = artifactProperties; } @@ -58,13 +51,11 @@ public static void main(String[] ignored) { try { ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); // Client builders. - ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.publisher); - ArtifactoryDependenciesClientBuilder dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.publisher); + ArtifactoryManagerBuilder artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.publisher); // Load artifact and BuildInfo properties from publisher section in the BuildInfo.properties file. ArtifactoryClientConfiguration.DockerHandler dockerHandler = clientConfiguration.dockerHandler; // Init DockerPush. - DockerPush dockerPush = new DockerPush(buildInfoClientBuilder, - dependenciesClientBuilder, + DockerPush dockerPush = new DockerPush(artifactoryManagerBuilder, dockerHandler.getImageTag(), dockerHandler.getHost(), ArrayListMultimap.create(clientConfiguration.publisher.getMatrixParams().asMultimap()), @@ -92,12 +83,12 @@ public Build execute() { try { DockerJavaWrapper.pushImage(imageTag, username, password, host, env, logger); String imageId = DockerJavaWrapper.getImageIdFromTag(imageTag, host, env, logger); - DockerImage image = new DockerImage(imageId, imageTag, targetRepository, buildInfoClientBuilder, dependenciesClientBuilder, "", ""); + DockerImage image = new DockerImage(imageId, imageTag, targetRepository, artifactoryManagerBuilder, "", ""); Module module = image.generateBuildInfoModule(logger, DockerUtils.CommandType.Push); if (module.getArtifacts() == null || module.getArtifacts().size() == 0) { logger.warn("Could not find docker image: " + imageTag + " in Artifactory."); } else { - setImageLayersProps(image.getLayers(), artifactProperties, buildInfoClientBuilder); + setImageLayersProps(image.getLayers(), artifactProperties, artifactoryManagerBuilder); } Build build = new Build(); modulesList.add(module); @@ -113,29 +104,15 @@ public Build execute() { /** * Update each layer's properties with artifactProperties. */ - private void setImageLayersProps(DockerLayers layers, ArrayListMultimap artifactProperties, ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder) throws IOException { - if (layers == null){ + private void setImageLayersProps(DockerLayers layers, ArrayListMultimap artifactProperties, ArtifactoryManagerBuilder artifactoryManagerBuilder) throws IOException { + if (layers == null) { return; } - String artifactsPropsStr = buildMatrixParamsString(artifactProperties, false); - try (ArtifactoryBuildInfoClient buildInfoClient = buildInfoClientBuilder.build()) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { for (DockerLayer layer : layers.getLayers()) { - HttpEntity entity = null; - try (CloseableHttpResponse httpResponse = buildInfoClient.executeUpdateFileProperty(layer.getFullPath(), artifactsPropsStr)) { - entity = httpResponse.getEntity(); - validateSetImageLayersResponse(httpResponse); - } finally { - EntityUtils.consume(entity); - } + artifactoryManager.setProperties(layer.getFullPath(), artifactProperties, false); } } } - private void validateSetImageLayersResponse(HttpResponse httpResponse) throws IOException { - int code = httpResponse.getStatusLine().getStatusCode(); - if (code != 204) { - String response = DockerUtils.entityToString(httpResponse.getEntity()); - throw new IOException("Failed while trying to set properties on docker layer: " + response); - } - } } \ No newline at end of file diff --git a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/types/DockerImage.java b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/types/DockerImage.java index 2fb0e924c..e3c14db91 100644 --- a/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/types/DockerImage.java +++ b/build-info-extractor-docker/src/main/java/org/jfrog/build/extractor/docker/types/DockerImage.java @@ -1,11 +1,7 @@ package org.jfrog.build.extractor.docker.types; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; import org.jfrog.build.api.Artifact; import org.jfrog.build.api.Dependency; import org.jfrog.build.api.Module; @@ -16,20 +12,15 @@ import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ArtifactoryVersion; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.docker.DockerUtils; import java.io.IOException; import java.io.Serializable; -import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; -import static org.jfrog.build.extractor.docker.DockerUtils.entityToString; - public class DockerImage implements Serializable { private final String imageId; private final String imageTag; @@ -40,18 +31,16 @@ public class DockerImage implements Serializable { private final Properties buildInfoModuleProps = new Properties(); private final String os; private final String architecture; - private final ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; - private final ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; + private final ArtifactoryManagerBuilder artifactoryManagerBuilder; private String manifest; private String imagePath; private DockerLayers layers; - public DockerImage(String imageId, String imageTag, String targetRepo, ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, String arch, String os) { + public DockerImage(String imageId, String imageTag, String targetRepo, ArtifactoryManagerBuilder artifactoryManagerBuilder, String arch, String os) { this.imageId = imageId; this.imageTag = imageTag; this.targetRepo = targetRepo; - this.buildInfoClientBuilder = buildInfoClientBuilder; - this.dependenciesClientBuilder = dependenciesClientBuilder; + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.architecture = arch; this.os = os; } @@ -64,8 +53,8 @@ public DockerLayers getLayers() { * Check if the provided manifestPath is correct. * Set the manifest and imagePath in case of the correct manifest. */ - private void checkAndSetManifestAndImagePathCandidates(String candidateManifestPath, ArtifactoryDependenciesClient dependenciesClient, Log logger) throws IOException { - Pair candidateDetails = getManifestFromArtifactory(dependenciesClient, candidateManifestPath, logger); + private void checkAndSetManifestAndImagePathCandidates(String candidateManifestPath, ArtifactoryManager artifactoryManager, Log logger) throws IOException { + Pair candidateDetails = getManifestFromArtifactory(artifactoryManager, candidateManifestPath, logger); String manifestContent = candidateDetails.getLeft(); String manifestPath = candidateDetails.getRight(); String imageDigest = DockerUtils.getConfigDigest(manifestContent); @@ -82,50 +71,37 @@ private void checkAndSetManifestAndImagePathCandidates(String candidateManifestP * In order to find the right digest, we read and iterate on each digest and search for the one with the same os and arch. * By using the correct digest from the fat-manifest, we are able to build the path toward manifest.json in Artifactory. * - * @param dependenciesClient - Dependencies client builder. + * @param artifactoryManager - Artifactory Manager. * @param manifestPath - Path to manifest in Artifactory. * @return A pair of (manifest content, path to manifest). * @throws IOException fail to search for manifest json in manifestPath. */ - private Pair getManifestFromArtifactory(ArtifactoryDependenciesClient dependenciesClient, String manifestPath, Log logger) throws IOException { - String artUrl = dependenciesClient.getArtifactoryUrl() + "/"; + private Pair getManifestFromArtifactory(ArtifactoryManager artifactoryManager, String manifestPath, Log logger) throws IOException { String pathWithoutRepo = StringUtils.substringAfter(manifestPath, "/"); - HttpEntity entity = null; - String downloadUrl = artUrl + manifestPath + "/manifest.json"; + String downloadUrl = manifestPath + "/manifest.json"; logger.info("Trying to download manifest from " + downloadUrl); - try (CloseableHttpResponse response = dependenciesClient.downloadArtifact(downloadUrl)) { - entity = response.getEntity(); - return Pair.of(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8.name()), pathWithoutRepo); + try { + return Pair.of(artifactoryManager.download(downloadUrl), pathWithoutRepo); } catch (Exception e) { - if (dependenciesClient.isLocalRepo(targetRepo)) { + if (artifactoryManager.isLocalRepo(targetRepo)) { throw e; } - EntityUtils.consume(entity); - downloadUrl = artUrl + manifestPath + "/list.manifest.json"; + downloadUrl = manifestPath + "/list.manifest.json"; logger.info("Fallback for remote/virtual repository. Trying to download fat-manifest from " + downloadUrl); - try (CloseableHttpResponse response = dependenciesClient.downloadArtifact(downloadUrl)) { - entity = response.getEntity(); - String digestsFromFatManifest = DockerUtils.getImageDigestFromFatManifest(entityToString(response.getEntity()), os, architecture); - if (digestsFromFatManifest.isEmpty()) { - logger.info("Failed to get image digest from fat manifest"); - throw e; - } - logger.info("Found image digest from fat manifest. Trying to download the resulted manifest from path: " + manifestPath); - // Remove the tag from the pattern, and place the manifest digest instead. - manifestPath = StringUtils.substringBeforeLast(manifestPath, "/") + "/" + digestsFromFatManifest.replace(":", "__"); - } - - EntityUtils.consume(entity); - downloadUrl = artUrl + manifestPath + "/manifest.json"; - logger.info("Trying to download manifest from " + downloadUrl); - try (CloseableHttpResponse response = dependenciesClient.downloadArtifact(downloadUrl)) { - entity = response.getEntity(); - pathWithoutRepo = StringUtils.substringAfter(manifestPath, "/"); - return Pair.of(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8.name()), pathWithoutRepo); + String digestsFromFatManifest = DockerUtils.getImageDigestFromFatManifest(artifactoryManager.download(downloadUrl), os, architecture); + if (digestsFromFatManifest.isEmpty()) { + logger.info("Failed to get image digest from fat manifest"); + throw e; } - } finally { - EntityUtils.consumeQuietly(entity); + logger.info("Found image digest from fat manifest. Trying to download the resulted manifest from path: " + manifestPath); + // Remove the tag from the pattern, and place the manifest digest instead. + manifestPath = StringUtils.substringBeforeLast(manifestPath, "/") + "/" + digestsFromFatManifest.replace(":", "__"); } + + downloadUrl = manifestPath + "/manifest.json"; + logger.info("Trying to download manifest from " + downloadUrl); + return Pair.of(artifactoryManager.download(downloadUrl), pathWithoutRepo); + } private void setBuildInfoModuleProps(ModuleBuilder moduleBuilder) { @@ -134,8 +110,8 @@ private void setBuildInfoModuleProps(ModuleBuilder moduleBuilder) { moduleBuilder.properties(buildInfoModuleProps); } - private DockerLayers createLayers(ArtifactoryDependenciesClient dependenciesClient, String aql) throws IOException { - AqlSearchResult result = dependenciesClient.searchArtifactsByAql(aql); + private DockerLayers createLayers(ArtifactoryManager artifactoryManager, String aql) throws IOException { + AqlSearchResult result = artifactoryManager.searchArtifactsByAql(aql); DockerLayers layers = new DockerLayers(); for (AqlSearchResult.SearchEntry entry : result.getResults()) { DockerLayer layer = new DockerLayer(entry); @@ -150,15 +126,12 @@ private DockerLayers createLayers(ArtifactoryDependenciesClient dependenciesClie /** * Search the docker image in Artifactory and add all artifacts & dependencies into Module. */ - private void setDependenciesAndArtifacts(ModuleBuilder moduleBuilder, ArtifactoryDependenciesClient dependenciesClient) throws IOException { + private void setDependenciesAndArtifacts(ModuleBuilder moduleBuilder, ArtifactoryManager artifactoryManager) throws IOException { DockerLayer historyLayer = layers.getByDigest(imageId); if (historyLayer == null) { throw new IllegalStateException("Could not find the history docker layer: " + imageId + " for image: " + imageTag + " in Artifactory."); } - HttpEntity entity = null; - try (CloseableHttpResponse res = dependenciesClient.downloadArtifact(dependenciesClient.getArtifactoryUrl() + "/" + historyLayer.getFullPath())) { - entity = res.getEntity(); - int dependencyLayerNum = DockerUtils.getNumberOfDependentLayers(entityToString(res.getEntity())); + int dependencyLayerNum = DockerUtils.getNumberOfDependentLayers(artifactoryManager.download(historyLayer.getFullPath())); LinkedHashSet dependencies = new LinkedHashSet<>(); LinkedHashSet artifacts = new LinkedHashSet<>(); @@ -184,9 +157,6 @@ private void setDependenciesAndArtifacts(ModuleBuilder moduleBuilder, Artifactor artifacts.add(artifact); } moduleBuilder.artifacts(new ArrayList<>(artifacts)); - } finally { - EntityUtils.consume(entity); - } } private void setDependencies(ModuleBuilder moduleBuilder) throws IOException { @@ -217,14 +187,14 @@ private String getAqlQuery(boolean includeVirtualRepos, String Repo, String mani return aqlRequestForDockerSha.toString(); } - public Module generateBuildInfoModule(Log logger, DockerUtils.CommandType cmdType) throws IOException { - try (ArtifactoryDependenciesClient dependenciesClient = dependenciesClientBuilder.build()) { + public Module generateBuildInfoModule(Log logger, DockerUtils.CommandType cmdType) throws IOException, InterruptedException { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { ModuleBuilder moduleBuilder = new ModuleBuilder() .type(ModuleType.DOCKER) .id(imageTag.substring(imageTag.indexOf("/") + 1)) .repository(targetRepo); try { - findAndSetManifestFromArtifactory(dependenciesClient, logger, cmdType); + findAndSetManifestFromArtifactory(artifactoryManager, logger, cmdType); } catch (IOException e) { // The manifest could not be found in Artifactory. // Yet, we do not fail the build, but return an empty build-info instead. @@ -237,7 +207,7 @@ public Module generateBuildInfoModule(Log logger, DockerUtils.CommandType cmdTyp } logger.info("Fetching details of published docker layers from Artifactory..."); if (cmdType == DockerUtils.CommandType.Push) { - setDependenciesAndArtifacts(moduleBuilder, dependenciesClient); + setDependenciesAndArtifacts(moduleBuilder, artifactoryManager); } else { setDependencies(moduleBuilder); } @@ -247,9 +217,8 @@ public Module generateBuildInfoModule(Log logger, DockerUtils.CommandType cmdTyp } private void loadLayers(String manifestPath) throws IOException { - try (ArtifactoryBuildInfoClient buildInfoClient = buildInfoClientBuilder.build(); - ArtifactoryDependenciesClient dependenciesClient = dependenciesClientBuilder.build()) { - layers = getLayers(dependenciesClient, buildInfoClient, manifestPath); + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + layers = getLayers(artifactoryManager, manifestPath); List markerLayers = layers.getLayers().stream().filter(layer -> layer.getFileName().endsWith(".marker")).collect(Collectors.toList()); // Transform all marker layers into regular layer. if (markerLayers.size() > 0) { @@ -257,36 +226,36 @@ private void loadLayers(String manifestPath) throws IOException { // Get image name without '.marker' suffix. String imageDigests = StringUtils.removeEnd(markerLayer.getDigest(), ".marker"); String imageName = StringUtils.substringBetween(imageTag, "/", ":"); - DockerUtils.downloadMarkerLayer(targetRepo, imageName, imageDigests, dependenciesClient); + DockerUtils.downloadMarkerLayer(targetRepo, imageName, imageDigests, artifactoryManager); } - layers = getLayers(dependenciesClient, buildInfoClient, manifestPath); + layers = getLayers(artifactoryManager, manifestPath); } } } - private DockerLayers getLayers(ArtifactoryDependenciesClient dependenciesClient, ArtifactoryBuildInfoClient buildInfoClient, String manifestPath) throws IOException { + private DockerLayers getLayers(ArtifactoryManager artifactoryManager, String manifestPath) throws IOException { String searchableRepo = targetRepo; - if (dependenciesClient.isRemoteRepo(targetRepo)) { + if (artifactoryManager.isRemoteRepo(targetRepo)) { searchableRepo += "-cache"; } - String aql = getAqlQuery(buildInfoClient.getArtifactoryVersion().isAtLeast(VIRTUAL_REPOS_SUPPORTED_VERSION), searchableRepo, manifestPath); - return createLayers(dependenciesClient, aql); + String aql = getAqlQuery(artifactoryManager.getVersion().isAtLeast(VIRTUAL_REPOS_SUPPORTED_VERSION), searchableRepo, manifestPath); + return createLayers(artifactoryManager, aql); } /** * Find and validate manifest.json file in Artifactory for the current image. * Since provided imageTag differs between reverse-proxy and proxy-less configuration, try to build the correct manifest path. */ - private void findAndSetManifestFromArtifactory(ArtifactoryDependenciesClient dependenciesClient, Log logger, DockerUtils.CommandType cmdType) throws IOException { + private void findAndSetManifestFromArtifactory(ArtifactoryManager artifactoryManager, Log logger, DockerUtils.CommandType cmdType) throws IOException { // Try to get manifest, assuming reverse proxy String ImagePath = DockerUtils.getImagePath(imageTag); ArrayList manifestPathCandidate = new ArrayList<>(DockerUtils.getArtManifestPath(ImagePath, targetRepo, cmdType)); - logger.info("Searching manifest for image \"" + imageTag + "\" in \"" + dependenciesClient.getArtifactoryUrl() + "\" under \"" + targetRepo + "\" repository"); + logger.info("Searching manifest for image \"" + imageTag + "\" in \"" + artifactoryManager.getUrl() + "\" under \"" + targetRepo + "\" repository"); int listLen = manifestPathCandidate.size(); for (int i = 0; i < listLen; i++) { try { logger.info("Searching manifest in path: " + manifestPathCandidate.get(i)); - checkAndSetManifestAndImagePathCandidates(manifestPathCandidate.get(i), dependenciesClient, logger); + checkAndSetManifestAndImagePathCandidates(manifestPathCandidate.get(i), artifactoryManager, logger); return; } catch (IOException e) { // Throw the exception only if we reached the end of the loop, which means we tried all options. diff --git a/build-info-extractor-docker/src/test/java/org/jfrog/build/extractor/docker/extractor/DockerExtractorTest.java b/build-info-extractor-docker/src/test/java/org/jfrog/build/extractor/docker/extractor/DockerExtractorTest.java index 4a76578a3..e8a67a207 100644 --- a/build-info-extractor-docker/src/test/java/org/jfrog/build/extractor/docker/extractor/DockerExtractorTest.java +++ b/build-info-extractor-docker/src/test/java/org/jfrog/build/extractor/docker/extractor/DockerExtractorTest.java @@ -10,8 +10,7 @@ import org.jfrog.build.api.Build; import org.jfrog.build.api.Dependency; import org.jfrog.build.api.Module; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.docker.DockerJavaWrapper; import org.testng.SkipException; import org.testng.annotations.AfterClass; @@ -43,8 +42,7 @@ public class DockerExtractorTest extends IntegrationTestsBase { private static final String DOCKER_VIRTUAL_REPO = "BITESTS_ARTIFACTORY_DOCKER_VIRTUAL_REPO"; private static final String DOCKER_HOST = "BITESTS_ARTIFACTORY_DOCKER_HOST"; private final ArrayListMultimap artifactProperties = ArrayListMultimap.create(); - private ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; - private ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; private String localDomainName; private String remoteDomainName; private String pullImageFromVirtual; @@ -74,8 +72,7 @@ private static boolean isWindows() { @BeforeClass private void setUp() { - dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); - buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); + artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); // Get image name localDomainName = validateDomainSuffix(System.getenv(LOCAL_DOMAIN)); remoteDomainName = validateDomainSuffix(System.getenv(REMOTE_DOMAIN)); @@ -105,7 +102,7 @@ public void dockerPushFromLocalTest() { String projectPath = PROJECTS_ROOT.resolve("docker-push").toAbsolutePath().toString(); DockerJavaWrapper.buildImage(imageTagLocal, host, Collections.emptyMap(), projectPath); - DockerPush dockerPush = new DockerPush(buildInfoClientBuilder, dependenciesClientBuilder, imageTagLocal, host, artifactProperties, dockerLocalRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); + DockerPush dockerPush = new DockerPush(artifactoryManagerBuilder, imageTagLocal, host, artifactProperties, dockerLocalRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); Build build = dockerPush.execute(); assertEquals(build.getModules().size(), 1); Module module = build.getModules().get(0); @@ -137,7 +134,7 @@ public void dockerPushFromVirtualTest() { String projectPath = PROJECTS_ROOT.resolve("docker-push").toAbsolutePath().toString(); DockerJavaWrapper.buildImage(imageTagVirtual, host, Collections.emptyMap(), projectPath); - DockerPush dockerPush = new DockerPush(buildInfoClientBuilder, dependenciesClientBuilder, imageTagVirtual, host, artifactProperties, dockerVirtualRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); + DockerPush dockerPush = new DockerPush(artifactoryManagerBuilder, imageTagVirtual, host, artifactProperties, dockerVirtualRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); Build build = dockerPush.execute(); assertEquals(build.getModules().size(), 1); Module module = build.getModules().get(0); @@ -167,7 +164,7 @@ public void dockerPullFromRemoteTest() { if (StringUtils.isBlank(dockerRemoteRepo)) { throw new IOException("The " + DOCKER_REMOTE_REPO + " environment variable is not set, failing docker tests."); } - DockerPull dockerPull = new DockerPull(buildInfoClientBuilder, dependenciesClientBuilder, pullImageFromRemote, host, dockerRemoteRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); + DockerPull dockerPull = new DockerPull(artifactoryManagerBuilder, pullImageFromRemote, host, dockerRemoteRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); validatePulledDockerImage(dockerPull.execute(), pullImageFromRemote); } catch (Exception e) { fail(ExceptionUtils.getStackTrace(e)); @@ -187,7 +184,7 @@ public void dockerPullFromVirtualTest() { if (StringUtils.isBlank(dockerVirtualRepo)) { throw new IOException("The " + DOCKER_VIRTUAL_REPO + " environment variable is not set, failing docker tests."); } - DockerPull dockerPull = new DockerPull(buildInfoClientBuilder, dependenciesClientBuilder, pullImageFromVirtual, host, dockerVirtualRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); + DockerPull dockerPull = new DockerPull(artifactoryManagerBuilder, pullImageFromVirtual, host, dockerVirtualRepo, getUsername(), getPassword(), getLog(), Collections.emptyMap()); validatePulledDockerImage(dockerPull.execute(), pullImageFromVirtual); } catch (Exception e) { fail(ExceptionUtils.getStackTrace(e)); diff --git a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoCommand.java b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoCommand.java index ed1be9fc1..90f844eb8 100644 --- a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoCommand.java +++ b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoCommand.java @@ -1,17 +1,10 @@ package org.jfrog.build.extractor.go.extractor; import org.apache.commons.lang.StringUtils; -import org.jfrog.build.api.Artifact; -import org.jfrog.build.api.Build; -import org.jfrog.build.api.Dependency; -import org.jfrog.build.api.Module; -import org.jfrog.build.api.builder.ModuleBuilder; -import org.jfrog.build.api.builder.ModuleType; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ArtifactoryVersion; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientBuilderBase; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.go.GoDriver; import org.jfrog.build.util.VersionCompatibilityType; import org.jfrog.build.util.VersionException; @@ -20,8 +13,6 @@ import java.io.IOException; import java.io.Serializable; import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; /** * Base class for go build and go publish commands. @@ -35,7 +26,7 @@ abstract class GoCommand implements Serializable { private static final long serialVersionUID = 1L; private static final ArtifactoryVersion MIN_SUPPORTED_ARTIFACTORY_VERSION = new ArtifactoryVersion("6.10.0"); - ArtifactoryClientBuilderBase clientBuilder; + ArtifactoryManagerBuilder artifactoryManagerBuilder; GoDriver goDriver; Path path; // Module name, as specified in go.mod, is used for naming the relevant go package files. @@ -45,20 +36,20 @@ abstract class GoCommand implements Serializable { String buildInfoModuleId; Log logger; - GoCommand(ArtifactoryBuildInfoClientBuilder clientBuilder, Path path, String buildInfoModuleId, Log logger) throws IOException { - this.clientBuilder = clientBuilder; + GoCommand(ArtifactoryManagerBuilder artifactoryManagerBuilder, Path path, String buildInfoModuleId, Log logger) { + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.logger = logger; this.path = path; this.buildInfoModuleId = buildInfoModuleId; } - protected void preparePrerequisites(String repo, ArtifactoryBaseClient client) throws VersionException, IOException { - validateArtifactoryVersion(client); - validateRepoExists(repo, client, "The provided repo must be specified"); + protected void preparePrerequisites(String repo, ArtifactoryManager artifactoryManager) throws VersionException, IOException { + validateArtifactoryVersion(artifactoryManager); + validateRepoExists(repo, artifactoryManager, "The provided repo must be specified"); } - private void validateArtifactoryVersion(ArtifactoryBaseClient client) throws VersionException { - ArtifactoryVersion version = client.getArtifactoryVersion(); + private void validateArtifactoryVersion(ArtifactoryManager artifactoryManager) throws VersionException, IOException { + ArtifactoryVersion version = artifactoryManager.getVersion(); if (version.isNotFound()) { String message = "Couldn't execute go task. Check connection with Artifactory."; throw new VersionException(message, VersionCompatibilityType.NOT_FOUND); @@ -69,11 +60,11 @@ private void validateArtifactoryVersion(ArtifactoryBaseClient client) throws Ver } } - private void validateRepoExists(String repo, ArtifactoryBaseClient client, String repoNotSpecifiedMsg) throws IOException { + private void validateRepoExists(String repo, ArtifactoryManager artifactoryManager, String repoNotSpecifiedMsg) throws IOException { if (StringUtils.isBlank(repo)) { throw new IllegalArgumentException(repoNotSpecifiedMsg); } - if (!client.isRepoExist(repo)) { + if (!artifactoryManager.isRepositoryExist(repo)) { throw new IOException("Repo " + repo + " doesn't exist"); } } diff --git a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoPublish.java b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoPublish.java index 9d6da066e..572c2fe58 100644 --- a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoPublish.java +++ b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoPublish.java @@ -13,8 +13,8 @@ import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ArtifactoryUploadResponse; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.go.GoDriver; @@ -48,15 +48,15 @@ public class GoPublish extends GoCommand { /** * Publish go package. * - * @param clientBuilder - Client builder for deployment. - * @param properties - Properties to set on each deployed artifact (Build name, Build number, etc...). - * @param repo - Artifactory's repository for deployment. - * @param path - Path to directory contains go.mod. - * @param version - The package's version. - * @param logger - The logger. + * @param artifactoryManagerBuilder - Artifactory Manager builder for deployment. + * @param properties - Properties to set on each deployed artifact (Build name, Build number, etc...). + * @param repo - Artifactory's repository for deployment. + * @param path - Path to directory contains go.mod. + * @param version - The package's version. + * @param logger - The logger. */ - public GoPublish(ArtifactoryBuildInfoClientBuilder clientBuilder, ArrayListMultimap properties, String repo, Path path, String version, String module, Log logger) throws IOException { - super(clientBuilder, path, module, logger); + public GoPublish(ArtifactoryManagerBuilder artifactoryManagerBuilder, ArrayListMultimap properties, String repo, Path path, String version, String module, Log logger) throws IOException { + super(artifactoryManagerBuilder, path, module, logger); this.goDriver = new GoDriver(GO_CLIENT_CMD, null, path.toFile(), logger); this.moduleName = goDriver.getModuleName(); this.properties = properties; @@ -65,9 +65,9 @@ public GoPublish(ArtifactoryBuildInfoClientBuilder clientBuilder, ArrayListMulti } public Build execute() { - try (ArtifactoryBuildInfoClient artifactoryClient = (ArtifactoryBuildInfoClient) clientBuilder.build()) { - preparePrerequisites(deploymentRepo, artifactoryClient); - publishPkg(artifactoryClient); + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + preparePrerequisites(deploymentRepo, artifactoryManager); + publishPkg(artifactoryManager); return createBuild(); } catch (Exception e) { logger.error(e.getMessage(), e); @@ -81,13 +81,13 @@ public Build execute() { * 2. go.mod file. * 3. go.info file. */ - private void publishPkg(ArtifactoryBuildInfoClient client) throws Exception { - createAndDeployZip(client); - deployGoMod(client); - createAndDeployInfo(client); + private void publishPkg(ArtifactoryManager artifactoryManager) throws Exception { + createAndDeployZip(artifactoryManager); + deployGoMod(artifactoryManager); + createAndDeployInfo(artifactoryManager); } - private void createAndDeployZip(ArtifactoryBuildInfoClient client) throws Exception { + private void createAndDeployZip(ArtifactoryManager artifactoryManager) throws Exception { // First, we create a temporary zip file of all project files. File tmpZipFile = archiveProjectDir(); @@ -96,7 +96,7 @@ private void createAndDeployZip(ArtifactoryBuildInfoClient client) throws Except File deployableZipFile = File.createTempFile(LOCAL_PKG_FILENAME, PKG_ZIP_FILE_EXTENSION, path.toFile()); try (GoZipBallStreamer pkgArchiver = new GoZipBallStreamer(new ZipFile(tmpZipFile), moduleName, version, logger)) { pkgArchiver.writeDeployableZip(deployableZipFile); - Artifact deployedPackage = deploy(client, deployableZipFile, PKG_ZIP_FILE_EXTENSION); + Artifact deployedPackage = deploy(artifactoryManager, deployableZipFile, PKG_ZIP_FILE_EXTENSION); artifactList.add(deployedPackage); } finally { Files.deleteIfExists(tmpZipFile.toPath()); @@ -104,16 +104,16 @@ private void createAndDeployZip(ArtifactoryBuildInfoClient client) throws Except } } - private void deployGoMod(ArtifactoryBuildInfoClient client) throws Exception { + private void deployGoMod(ArtifactoryManager artifactoryManager) throws Exception { String modLocalPath = getModFilePath(); - Artifact deployedMod = deploy(client, new File(modLocalPath), PKG_MOD_FILE_EXTENSION); + Artifact deployedMod = deploy(artifactoryManager, new File(modLocalPath), PKG_MOD_FILE_EXTENSION); artifactList.add(deployedMod); } - private void createAndDeployInfo(ArtifactoryBuildInfoClient client) throws Exception { + private void createAndDeployInfo(ArtifactoryManager artifactoryManager) throws Exception { String infoLocalPath = path.toString() + File.separator + LOCAL_INFO_FILENAME; File infoFile = writeInfoFile(infoLocalPath); - Artifact deployedInfo = deploy(client, infoFile, PKG_INFO_FILE_EXTENSION); + Artifact deployedInfo = deploy(artifactoryManager, infoFile, PKG_INFO_FILE_EXTENSION); artifactList.add(deployedInfo); infoFile.delete(); } @@ -160,7 +160,7 @@ private File writeInfoFile(String localInfoPath) throws IOException { /** * Deploy pkg file and add it as an buildInfo's artifact */ - private Artifact deploy(ArtifactoryBuildInfoClient client, File deployedFile, String extension) throws Exception { + private Artifact deploy(ArtifactoryManager artifactoryManager, File deployedFile, String extension) throws Exception { String artifactName = version + "." + extension; Map checksums = FileChecksumCalculator.calculateChecksums(deployedFile, MD5, SHA1); String remotePath = moduleName + "/@v"; @@ -173,7 +173,7 @@ private Artifact deploy(ArtifactoryBuildInfoClient client, File deployedFile, St .packageType(DeployDetails.PackageType.GO) .build(); - ArtifactoryUploadResponse response = client.deployArtifact(deployDetails); + ArtifactoryUploadResponse response = artifactoryManager.upload(deployDetails); return new ArtifactBuilder(moduleName + ":" + artifactName) .md5(response.getChecksums().getMd5()) diff --git a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoRun.java b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoRun.java index 15fdb2f98..153e9c338 100644 --- a/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoRun.java +++ b/build-info-extractor-go/src/main/java/org/jfrog/build/extractor/go/extractor/GoRun.java @@ -9,8 +9,8 @@ import org.jfrog.build.api.builder.ModuleType; import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.executor.CommandResults; import org.jfrog.build.extractor.go.GoDriver; import org.jfrog.build.extractor.packageManager.PackageManagerUtils; @@ -54,17 +54,17 @@ public class GoRun extends GoCommand { /** * Run go command and collect dependencies. * - * @param goCmdArgs - Go cmd args. - * @param path - Path to directory contains go.mod. - * @param clientBuilder - Client builder for resolution. - * @param repo - Artifactory's repository for resolution. - * @param username - Artifactory's username for resolution. - * @param password - Artifactory's password for resolution. - * @param logger - The logger. - * @param env - Environment variables to use during npm execution. + * @param goCmdArgs - Go cmd args. + * @param path - Path to directory contains go.mod. + * @param artifactoryManagerBuilder - Manager builder for resolution. + * @param repo - Artifactory's repository for resolution. + * @param username - Artifactory's username for resolution. + * @param password - Artifactory's password for resolution. + * @param logger - The logger. + * @param env - Environment variables to use during npm execution. */ - public GoRun(String goCmdArgs, Path path, String buildInfoModuleId, ArtifactoryBuildInfoClientBuilder clientBuilder, String repo, String username, String password, Log logger, Map env) throws IOException { - super(clientBuilder, path, buildInfoModuleId, logger); + public GoRun(String goCmdArgs, Path path, String buildInfoModuleId, ArtifactoryManagerBuilder artifactoryManagerBuilder, String repo, String username, String password, Log logger, Map env) { + super(artifactoryManagerBuilder, path, buildInfoModuleId, logger); this.env = env; this.goCmdArgs = goCmdArgs; this.resolutionRepository = repo; @@ -73,7 +73,7 @@ public GoRun(String goCmdArgs, Path path, String buildInfoModuleId, ArtifactoryB } public Build execute() { - try (ArtifactoryBuildInfoClient artifactoryClient = (clientBuilder != null ? (ArtifactoryBuildInfoClient) clientBuilder.build() : null)) { + try (ArtifactoryManager artifactoryClient = (artifactoryManagerBuilder != null ? artifactoryManagerBuilder.build() : null)) { if (artifactoryClient != null) { preparePrerequisites(resolutionRepository, artifactoryClient); setResolverAsGoProxy(artifactoryClient); @@ -96,8 +96,8 @@ public Build execute() { * In order to use Artifactory as a resolver we need to set GOPROXY env var with Artifactory details. * Wa also support fallback to VCS in case pkg doesn't exist in Artifactort, */ - private void setResolverAsGoProxy(ArtifactoryBuildInfoClient client) throws Exception { - String rtUrl = PackageManagerUtils.createArtifactoryUrlWithCredentials(client.getArtifactoryUrl(), resolverUsername, resolverPassword, ARTIFACTORY_GO_API + resolutionRepository); + private void setResolverAsGoProxy(ArtifactoryManager artifactoryClient) throws Exception { + String rtUrl = PackageManagerUtils.createArtifactoryUrlWithCredentials(artifactoryClient.getUrl(), resolverUsername, resolverPassword, ARTIFACTORY_GO_API + resolutionRepository); String proxyValue = rtUrl + "," + GOPROXY_VCS_FALLBACK; env.put(GOPROXY_ENV_VAR, proxyValue); } diff --git a/build-info-extractor-go/src/test/java/org/jfrog/build/extractor/go/extractor/GoExtractorTest.java b/build-info-extractor-go/src/test/java/org/jfrog/build/extractor/go/extractor/GoExtractorTest.java index 14af93ac0..abb3c4774 100644 --- a/build-info-extractor-go/src/test/java/org/jfrog/build/extractor/go/extractor/GoExtractorTest.java +++ b/build-info-extractor-go/src/test/java/org/jfrog/build/extractor/go/extractor/GoExtractorTest.java @@ -7,7 +7,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.jfrog.build.IntegrationTestsBase; import org.jfrog.build.api.*; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.executor.CommandExecutor; import org.testng.annotations.BeforeClass; @@ -36,7 +36,7 @@ public class GoExtractorTest extends IntegrationTestsBase { private static final Path PROJECTS_ROOT = Paths.get(".").toAbsolutePath().normalize().resolve(Paths.get("src", "test", "resources", "org", "jfrog", "build", "extractor")); - private ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; private final Map env = new TreeMap<>(); public GoExtractorTest() { @@ -100,7 +100,7 @@ private Set getArtifactSet() { @BeforeClass private void setUp() throws IOException { - buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); + artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); deployTestDependencies(Project.QUOTE, Project.SAMPLER, Project.TEXT); } @@ -116,7 +116,7 @@ private void deployTestDependencies(Project... projects) throws IOException { .artifactPath(project.getTargetPath(ext)) .packageType(DeployDetails.PackageType.GO) .build(); - buildInfoClient.deployArtifact(deployDetails); + artifactoryManager.upload(deployDetails); } } } @@ -139,17 +139,17 @@ private void cleanGoModCacheAndEnv() throws IOException, InterruptedException { private Object[][] goRunProvider() { return new Object[][]{ {Project.PROJECT_1, GO_BUILD_CMD, null, StringUtils.EMPTY}, - {Project.PROJECT_1, GO_BUILD_CMD, buildInfoClientBuilder, localRepo1}, + {Project.PROJECT_1, GO_BUILD_CMD, artifactoryManagerBuilder, localRepo1}, }; } @Test(dataProvider = "goRunProvider") - public void goRunTest(Project project, String args, ArtifactoryBuildInfoClientBuilder clientBuilder, String repo) { + public void goRunTest(Project project, String args, ArtifactoryManagerBuilder artifactoryManagerBuilder, String repo) { Path projectDir = null; try { // Run Go build projectDir = createProjectDir(project.targetDir, project.projectOrigin); - GoRun goRun = new GoRun(args, projectDir, null, clientBuilder, repo, getUsername(), getPassword(), getLog(), env); + GoRun goRun = new GoRun(args, projectDir, null, artifactoryManagerBuilder, repo, getUsername(), getPassword(), getLog(), env); Build build = goRun.execute(); // Check successful execution and correctness of the module and dependencies assertNotNull(build); @@ -186,7 +186,7 @@ public void goRunPublishTest() { // Check successful execution assertNotNull(project1Build); // Publish project1 to Artifactory - GoPublish goPublish = new GoPublish(buildInfoClientBuilder, properties, localRepo1, projectDir, project.getVersion(), null, getLog()); + GoPublish goPublish = new GoPublish(artifactoryManagerBuilder, properties, localRepo1, projectDir, project.getVersion(), null, getLog()); Build publishBuild = goPublish.execute(); // Check successful execution assertNotNull(publishBuild); @@ -207,7 +207,7 @@ public void goRunPublishTest() { // Run Go build on project2 using Artifactory for resolution project = Project.PROJECT_2; projectDir = createProjectDir(project.targetDir, project.projectOrigin); - goRun = new GoRun(GO_BUILD_CMD, projectDir, null, buildInfoClientBuilder, virtualRepo, getUsername(), getPassword(), getLog(), env); + goRun = new GoRun(GO_BUILD_CMD, projectDir, null, artifactoryManagerBuilder, virtualRepo, getUsername(), getPassword(), getLog(), env); Build project2Build = goRun.execute(); // Check successful execution and correctness of the module, dependencies and artifacts assertNotNull(project2Build); diff --git a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/extractor/GradleClientLogger.java b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/extractor/GradleClientLogger.java index 039102976..e3c6039ce 100644 --- a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/extractor/GradleClientLogger.java +++ b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/extractor/GradleClientLogger.java @@ -8,7 +8,7 @@ * Logger that is to be used for the HTTP client when using Gradle. * * @author Tomer Cohen - * @see org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient + * @see org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager */ public class GradleClientLogger implements Log { diff --git a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DeployTask.java b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DeployTask.java index 17f35d645..8463368f8 100644 --- a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DeployTask.java +++ b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DeployTask.java @@ -18,7 +18,7 @@ import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; import org.jfrog.build.extractor.clientConfiguration.IncludeExcludePatterns; import org.jfrog.build.extractor.clientConfiguration.PatternMatcher; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployableArtifactsUtils; import org.jfrog.build.extractor.retention.Utils; @@ -119,28 +119,23 @@ private void generateBuildInfoJson(ArtifactoryClientConfiguration accRoot, Build } private void handleBuildInfoDeployment(ArtifactoryClientConfiguration accRoot, Build build, Map> allDeployDetails) throws IOException { - ArtifactoryBuildInfoClient client = null; String contextUrl = accRoot.publisher.getContextUrl(); if (contextUrl != null) { - try { - client = new ArtifactoryBuildInfoClient( - accRoot.publisher.getContextUrl(), - accRoot.publisher.getUsername(), - accRoot.publisher.getPassword(), - new GradleClientLogger(log)); - configureProxy(accRoot, client); - configConnectionTimeout(accRoot, client); - configRetriesParams(accRoot, client); + try (ArtifactoryManager artifactoryManager = new ArtifactoryManager( + accRoot.publisher.getContextUrl(), + accRoot.publisher.getUsername(), + accRoot.publisher.getPassword(), + new GradleClientLogger(log))) { if (isPublishBuildInfo(accRoot)) { // If export property set always save the file before sending it to artifactory exportBuildInfo(build, getExportFile(accRoot)); if (accRoot.info.isIncremental()) { log.debug("Publishing build info modules to artifactory at: '{}'", contextUrl); - client.sendModuleInfo(build); + artifactoryManager.sendModuleInfo(build); } else { log.debug("Publishing build info to artifactory at: '{}'", contextUrl); - Utils.sendBuildAndBuildRetention(client, build, accRoot); + Utils.sendBuildAndBuildRetention(artifactoryManager, build, accRoot); } } if (isGenerateDeployableArtifactsToFile(accRoot)) { @@ -151,10 +146,6 @@ private void handleBuildInfoDeployment(ArtifactoryClientConfiguration accRoot, B throw new RuntimeException("Failed writing deployable artifacts to file", e); } } - } finally { - if (client != null) { - client.close(); - } } } } @@ -181,17 +172,16 @@ private void deployArtifacts(ArtifactoryClientConfiguration accRoot, Map allDeployDetails, ArtifactoryBuildInfoClient client, - IncludeExcludePatterns patterns, String logPrefix) + private void deployArtifacts(Set allDeployDetails, ArtifactoryManager artifactoryManager, + IncludeExcludePatterns patterns, String logPrefix, int MinChecksumDeploySizeKb) throws IOException { for (GradleDeployDetails detail : allDeployDetails) { DeployDetails deployDetails = detail.getDeployDetails(); @@ -288,7 +278,7 @@ private void deployArtifacts(Set allDeployDetails, Artifact "' due to the defined include-exclude patterns."); continue; } - client.deployArtifact(deployDetails, logPrefix); + artifactoryManager.upload(deployDetails, logPrefix, MinChecksumDeploySizeKb); } } diff --git a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DistributeBuildTask.java b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DistributeBuildTask.java index ae97b909b..00b30aa1e 100644 --- a/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DistributeBuildTask.java +++ b/build-info-extractor-gradle/src/main/groovy/org/jfrog/gradle/plugin/artifactory/task/DistributeBuildTask.java @@ -1,16 +1,13 @@ package org.jfrog.gradle.plugin.artifactory.task; import org.apache.commons.lang.StringUtils; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; import org.gradle.api.DefaultTask; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import org.gradle.api.tasks.TaskAction; import org.jfrog.build.api.release.Distribution; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention; import org.jfrog.gradle.plugin.artifactory.dsl.DistributerConfig; import org.jfrog.gradle.plugin.artifactory.extractor.GradleClientLogger; @@ -44,16 +41,9 @@ public void distributeBuild() throws IOException { new ArrayList<>(distributerConfig.getSourceRepoKeys()), distributerConfig.getDryRun()); - try (ArtifactoryBuildInfoClient client = new ArtifactoryBuildInfoClient(distributerConfig.getContextUrl(), - distributerConfig.getUsername(), distributerConfig.getPassword(), new GradleClientLogger(getLogger())); - CloseableHttpResponse response = client.distributeBuild(buildName, buildNumber, distribution)) { - String content = response.getEntity() != null ? EntityUtils.toString(response.getEntity(), "UTF-8") : ""; - EntityUtils.consumeQuietly(response.getEntity()); - StatusLine status = response.getStatusLine(); - if (status.getStatusCode() != 200) { - throw new IOException(String.format("Distribution failed. Received '%s', '%s' from Artifactory.", status.getReasonPhrase(), content)); - } - + try (ArtifactoryManager artifactoryManager = new ArtifactoryManager(distributerConfig.getContextUrl(), + distributerConfig.getUsername(), distributerConfig.getPassword(), new GradleClientLogger(getLogger()))) { + artifactoryManager.distributeBuild(buildName, buildNumber, distribution); log.info(String.format("Successfully distributed build %s/%s", clientConf.info.getBuildName(), clientConf.info.getBuildNumber())); } } diff --git a/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/GradlePluginTest.java b/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/GradlePluginTest.java index b7f325851..041c61f20 100644 --- a/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/GradlePluginTest.java +++ b/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/GradlePluginTest.java @@ -58,7 +58,7 @@ public void configurationsTest(String gradleVersion) throws IOException { // Run Gradle BuildResult buildResult = runGradle(gradleVersion, envVars, false); // Check results - checkBuildResults(dependenciesClient, buildInfoClient, buildResult, false, getUrl(), localRepo1); + checkBuildResults(artifactoryManager, buildResult, false, localRepo1); } @Test(dataProvider = "gradleVersions") @@ -68,7 +68,7 @@ public void publicationsTest(String gradleVersion) throws IOException { // Run Gradle BuildResult buildResult = runGradle(gradleVersion, envVars, false); // Check results - checkBuildResults(dependenciesClient, buildInfoClient, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, getUrl(), localRepo1); + checkBuildResults(artifactoryManager, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, localRepo1); } @Test(dataProvider = "gradleVersions") @@ -78,7 +78,7 @@ public void publicationsTestKotlinDsl(String gradleVersion) throws IOException { // Run Gradle BuildResult buildResult = runGradle(gradleVersion, envVars, false); // Check results - checkBuildResults(dependenciesClient, buildInfoClient, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, getUrl(), localRepo1); + checkBuildResults(artifactoryManager, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, localRepo1); } @Test(dataProvider = "gradleVersions") @@ -92,7 +92,7 @@ public void ciServerTest(String gradleVersion) throws IOException { // Run Gradle BuildResult buildResult = runGradle(gradleVersion, extendedEnv, true); // Check results - checkBuildResults(dependenciesClient, buildInfoClient, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, getUrl(), localRepo1); + checkBuildResults(artifactoryManager, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, localRepo1); } @Test(dataProvider = "gradleVersions") @@ -106,7 +106,7 @@ public void ciServerPublicationsTest(String gradleVersion) throws IOException { // Run Gradle BuildResult buildResult = runGradle(gradleVersion, extendedEnv, true); // Check results - checkBuildResults(dependenciesClient, buildInfoClient, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, getUrl(), localRepo1); + checkBuildResults(artifactoryManager, buildResult, VersionNumber.parse(gradleVersion).getMajor() >= 6, localRepo1); } @Test(dataProvider = "gradleVersions") diff --git a/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/Utils.java b/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/Utils.java index 29eec81ec..b6e6058d5 100644 --- a/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/Utils.java +++ b/build-info-extractor-gradle/src/test/java/org/jfrog/gradle/plugin/artifactory/Utils.java @@ -4,8 +4,6 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.text.StrSubstitutor; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.BuildTask; import org.gradle.testkit.runner.GradleRunner; @@ -13,8 +11,7 @@ import org.jfrog.build.api.Dependency; import org.jfrog.build.api.Module; import org.jfrog.build.api.util.CommonUtils; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.File; import java.io.IOException; @@ -25,7 +22,7 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS; import static org.jfrog.build.extractor.BuildInfoExtractorUtils.jsonStringToBuildInfo; -import static org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient.BUILD_BROWSE_URL; +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.PublishBuildInfo.BUILD_BROWSE_URL; import static org.jfrog.gradle.plugin.artifactory.Consts.*; import static org.testng.Assert.*; @@ -130,28 +127,24 @@ private static String generateBuildInfoPropertiesForServer(String contextUrl, St * 1. Check the build status of all tasks. * 2. Make sure all artifacts deployed. * - * @param dependenciesClient - Artifactory dependencies client - * @param buildInfoClient - The build info client + * @param artifactoryManager - ArtifactoryManager client * @param buildResult - The build results * @param expectModuleArtifacts - Should we expect *.module files - * @param url - Artifactory URL * @param localRepo - Artifactory local localRepo * @throws IOException - In case of any IO error */ - static void checkBuildResults(ArtifactoryDependenciesClient dependenciesClient, ArtifactoryBuildInfoClient buildInfoClient, BuildResult buildResult, boolean expectModuleArtifacts, String url, String localRepo) throws IOException { + static void checkBuildResults(ArtifactoryManager artifactoryManager, BuildResult buildResult, boolean expectModuleArtifacts, String localRepo) throws IOException { // Assert all tasks ended with success outcome assertProjectsSuccess(buildResult); // Check that all expected artifacts uploaded to Artifactory String[] expectedArtifacts = expectModuleArtifacts ? EXPECTED_MODULE_ARTIFACTS : EXPECTED_ARTIFACTS; for (String expectedArtifact : expectedArtifacts) { - try (CloseableHttpResponse response = dependenciesClient.getArtifactMetadata(url + localRepo + ARTIFACTS_GROUP_ID + expectedArtifact)) { - EntityUtils.consume(response.getEntity()); - } + artifactoryManager.downloadHeaders(localRepo + ARTIFACTS_GROUP_ID + expectedArtifact); } // Check build info - Build buildInfo = getBuildInfo(buildInfoClient, buildResult); + Build buildInfo = getBuildInfo(artifactoryManager, buildResult); assertNotNull(buildInfo); checkBuildInfoModules(buildInfo, 3, expectModuleArtifacts ? 5 : 4); } @@ -191,12 +184,12 @@ private static void assertRequestedBy(Build buildInfo) { /** * Get build info from the build info URL. * - * @param buildInfoClient - The build info client - * @param buildResult - The build results + * @param artifactoryManager - The ArtifactoryManager client + * @param buildResult - The build results * @return build info or null * @throws IOException - In case of any IO error */ - private static Build getBuildInfo(ArtifactoryBuildInfoClient buildInfoClient, BuildResult buildResult) throws IOException { + private static Build getBuildInfo(ArtifactoryManager artifactoryManager, BuildResult buildResult) throws IOException { // Get build info URL String[] res = StringUtils.substringAfter(buildResult.getOutput(), BUILD_BROWSE_URL).split("/"); assertTrue(ArrayUtils.getLength(res) >= 3, "Couldn't find build info URL link"); @@ -204,7 +197,7 @@ private static Build getBuildInfo(ArtifactoryBuildInfoClient buildInfoClient, Bu // Extract build name and number from build info URL String buildName = res[1]; String buildNumber = StringUtils.substringBefore(res[2], System.lineSeparator()); - return buildInfoClient.getBuildInfo(buildName, buildNumber, null); + return artifactoryManager.getBuildInfo(buildName, buildNumber, null); } /** diff --git a/build-info-extractor-ivy/src/main/java/org/jfrog/build/extractor/listener/ArtifactoryBuildListener.java b/build-info-extractor-ivy/src/main/java/org/jfrog/build/extractor/listener/ArtifactoryBuildListener.java index 5fb88888f..5ee0b1971 100644 --- a/build-info-extractor-ivy/src/main/java/org/jfrog/build/extractor/listener/ArtifactoryBuildListener.java +++ b/build-info-extractor-ivy/src/main/java/org/jfrog/build/extractor/listener/ArtifactoryBuildListener.java @@ -18,7 +18,7 @@ import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; import org.jfrog.build.extractor.clientConfiguration.IncludeExcludePatterns; import org.jfrog.build.extractor.clientConfiguration.PatternMatcher; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.packageManager.PackageManagerUtils; import org.jfrog.build.extractor.retention.Utils; @@ -96,7 +96,7 @@ public void buildStarted(BuildEvent event) { /** * Called when the build has ended, this is the time where we will assemble the build-info object that its * information was collected by the {@link org.jfrog.build.extractor.trigger.ArtifactoryBuildInfoTrigger} it will - * serialize the build-info object into a senadble JSON object to be used by the {@link org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient} + * serialize the build-info object into a senadble JSON object to be used by the {@link ArtifactoryManager} * * @param event The build event. */ @@ -358,18 +358,19 @@ private void doDeploy(BuildEvent event) { String contextUrl = clientConf.publisher.getContextUrl(); String username = clientConf.publisher.getUsername(); String password = clientConf.publisher.getPassword(); - try (ArtifactoryBuildInfoClient client = new ArtifactoryBuildInfoClient(contextUrl, username, password, log)) { - configureProxy(clientConf, client); - configConnectionTimeout(clientConf, client); - configRetriesParams(clientConf, client); + + try (ArtifactoryManager artifactoryManager = new ArtifactoryManager(contextUrl, username, password, log)) { + configureProxy(clientConf, artifactoryManager); + configConnectionTimeout(clientConf, artifactoryManager); + configRetriesParams(clientConf, artifactoryManager); if (clientConf.publisher.isPublishArtifacts()) { IncludeExcludePatterns patterns = new IncludeExcludePatterns( clientConf.publisher.getIncludePatterns(), clientConf.publisher.getExcludePatterns()); - deployArtifacts(project, client, deployDetails, patterns); + deployArtifacts(project, artifactoryManager, deployDetails, patterns); } if (clientConf.publisher.isPublishBuildInfo()) { - Utils.sendBuildAndBuildRetention(client, build, clientConf); + Utils.sendBuildAndBuildRetention(artifactoryManager, build, clientConf); } isDidDeploy = true; } catch (IOException e) { @@ -377,7 +378,7 @@ private void doDeploy(BuildEvent event) { } } - private void deployArtifacts(Project project, ArtifactoryBuildInfoClient client, Set deployDetails, + private void deployArtifacts(Project project, ArtifactoryManager artifactoryManager, Set deployDetails, IncludeExcludePatterns patterns) throws IOException { for (DeployDetails deployDetail : deployDetails) { String artifactPath = deployDetail.getArtifactPath(); @@ -386,11 +387,11 @@ private void deployArtifacts(Project project, ArtifactoryBuildInfoClient client, "' due to the defined include-exclude patterns.", Project.MSG_INFO); continue; } - client.deployArtifact(deployDetail); + artifactoryManager.upload(deployDetail); } } - protected void configureProxy(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { + protected void configureProxy(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { ArtifactoryClientConfiguration.ProxyHandler proxy = clientConf.proxy; String proxyHost = proxy.getHost(); if (StringUtils.isNotBlank(proxyHost) && proxy.getPort() != null) { @@ -398,22 +399,22 @@ protected void configureProxy(ArtifactoryClientConfiguration clientConf, Artifac String proxyUserName = proxy.getUsername(); if (StringUtils.isNotBlank(proxyUserName)) { buildInfoLog.debug("Found proxy user name '" + proxyUserName + "'"); - client.setProxyConfiguration(proxyHost, proxy.getPort(), proxyUserName, proxy.getPassword()); + artifactoryManager.setProxyConfiguration(proxyHost, proxy.getPort(), proxyUserName, proxy.getPassword()); } else { buildInfoLog.debug("No proxy user name and password found, using anonymous proxy"); - client.setProxyConfiguration(proxyHost, proxy.getPort()); + artifactoryManager.setProxyConfiguration(proxyHost, proxy.getPort()); } } } - protected void configConnectionTimeout(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { + protected void configConnectionTimeout(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { if (clientConf.getTimeout() != null) - client.setConnectionTimeout(clientConf.getTimeout()); + artifactoryManager.setConnectionTimeout(clientConf.getTimeout()); } - protected void configRetriesParams(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { + protected void configRetriesParams(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { if (clientConf.getConnectionRetries() != null) { - client.setConnectionRetries(clientConf.getConnectionRetries()); + artifactoryManager.setConnectionRetries(clientConf.getConnectionRetries()); } } } diff --git a/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildInfoClientBuilder.java b/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/ArtifactoryManagerBuilder.java similarity index 63% rename from build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildInfoClientBuilder.java rename to build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/ArtifactoryManagerBuilder.java index 8123478ff..18b8903ea 100644 --- a/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildInfoClientBuilder.java +++ b/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/ArtifactoryManagerBuilder.java @@ -6,32 +6,32 @@ import org.codehaus.plexus.logging.Logger; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; import org.jfrog.build.extractor.clientConfiguration.ClientConfigurationFields; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import static org.jfrog.build.extractor.clientConfiguration.ClientProperties.PROP_CONNECTION_RETRIES; import static org.jfrog.build.extractor.clientConfiguration.ClientProperties.PROP_TIMEOUT; /** - * Simple class to build {@link org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient} for deployment. + * Simple class to build {@link ArtifactoryManager} for deployment. * * @author Noam Y. Tenne */ -@Component(role = BuildInfoClientBuilder.class) -public class BuildInfoClientBuilder { +@Component(role = ArtifactoryManagerBuilder.class) +public class ArtifactoryManagerBuilder { @Requirement private Logger logger; - public ArtifactoryBuildInfoClient resolveProperties(ArtifactoryClientConfiguration clientConf) { - ArtifactoryBuildInfoClient client = resolveClientProps(clientConf); - resolveTimeout(clientConf, client); - resolveProxy(clientConf.proxy, client); - resolveRetriesParams(clientConf, client); - resolveInsecureTls(clientConf, client); - return client; + public ArtifactoryManager resolveProperties(ArtifactoryClientConfiguration clientConf) { + ArtifactoryManager artifactoryManager = resolveClientProps(clientConf); + resolveTimeout(clientConf, artifactoryManager); + resolveProxy(clientConf.proxy, artifactoryManager); + resolveRetriesParams(clientConf, artifactoryManager); + resolveInsecureTls(clientConf, artifactoryManager); + return artifactoryManager; } - private ArtifactoryBuildInfoClient resolveClientProps(ArtifactoryClientConfiguration clientConf) { + private ArtifactoryManager resolveClientProps(ArtifactoryClientConfiguration clientConf) { String contextUrl = clientConf.publisher.getContextUrl(); if (StringUtils.isBlank(contextUrl)) { throw new IllegalArgumentException( @@ -44,36 +44,36 @@ private ArtifactoryBuildInfoClient resolveClientProps(ArtifactoryClientConfigura if (StringUtils.isNotBlank(username)) { logResolvedProperty(ClientConfigurationFields.USERNAME, username); - return new ArtifactoryBuildInfoClient(contextUrl, username, password, new Maven3BuildInfoLogger(logger)); + return new ArtifactoryManager(contextUrl, username, password, new Maven3BuildInfoLogger(logger)); } else { - return new ArtifactoryBuildInfoClient(contextUrl, new Maven3BuildInfoLogger(logger)); + return new ArtifactoryManager(contextUrl, new Maven3BuildInfoLogger(logger)); } } - private void resolveTimeout(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { + private void resolveTimeout(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { if (clientConf.getTimeout() == null) { return; } int timeout = clientConf.getTimeout(); logResolvedProperty(PROP_TIMEOUT, String.valueOf(timeout)); - client.setConnectionTimeout(timeout); + artifactoryManager.setConnectionTimeout(timeout); } - private void resolveRetriesParams(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { + private void resolveRetriesParams(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { if (clientConf.getConnectionRetries() == null) { return; } int configMaxRetries = clientConf.getConnectionRetries(); logResolvedProperty(PROP_CONNECTION_RETRIES, String.valueOf(configMaxRetries)); - client.setConnectionRetries(configMaxRetries); + artifactoryManager.setConnectionRetries(configMaxRetries); } - private void resolveInsecureTls(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) { - client.setInsecureTls(clientConf.getInsecureTls()); + private void resolveInsecureTls(ArtifactoryClientConfiguration clientConf, ArtifactoryManager artifactoryManager) { + artifactoryManager.setInsecureTls(clientConf.getInsecureTls()); } private void resolveProxy(ArtifactoryClientConfiguration.ProxyHandler proxyConf, - ArtifactoryBuildInfoClient client) { + ArtifactoryManager artifactoryManager) { String proxyHost = proxyConf.getHost(); if (StringUtils.isNotBlank(proxyHost)) { @@ -84,10 +84,10 @@ private void resolveProxy(ArtifactoryClientConfiguration.ProxyHandler proxyConf, String proxyUsername = proxyConf.getUsername(); if (StringUtils.isNotBlank(proxyUsername)) { logResolvedProperty(ClientConfigurationFields.USERNAME, proxyUsername); - client.setProxyConfiguration(proxyHost, proxyConf.getPort(), proxyUsername, + artifactoryManager.setProxyConfiguration(proxyHost, proxyConf.getPort(), proxyUsername, proxyConf.getPassword()); } else { - client.setProxyConfiguration(proxyHost, proxyConf.getPort()); + artifactoryManager.setProxyConfiguration(proxyHost, proxyConf.getPort()); } } } diff --git a/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildDeploymentHelper.java b/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildDeploymentHelper.java index 3a5353aec..28d4a97f3 100644 --- a/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildDeploymentHelper.java +++ b/build-info-extractor-maven3/src/main/java/org/jfrog/build/extractor/maven/BuildDeploymentHelper.java @@ -26,11 +26,11 @@ import org.jfrog.build.api.Module; import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.extractor.BuildInfoExtractorUtils; +import org.jfrog.build.extractor.ModuleParallelDeployHelper; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployableArtifactsUtils; -import org.jfrog.build.extractor.ModuleParallelDeployHelper; import org.jfrog.build.extractor.retention.Utils; import java.io.File; @@ -46,7 +46,7 @@ public class BuildDeploymentHelper { @Requirement private Logger logger; @Requirement - private BuildInfoClientBuilder buildInfoClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; public void deploy( Build build, ArtifactoryClientConfiguration clientConf, @@ -84,8 +84,8 @@ public void deploy( Build build, } if (isDeployArtifacts(clientConf, wereThereTestFailures, deployableArtifactsByModule)) { - try (ArtifactoryBuildInfoClient client = buildInfoClientBuilder.resolveProperties(clientConf)) { - new ModuleParallelDeployHelper().deployArtifacts(client, deployableArtifactsByModule, clientConf.publisher.getPublishForkCount()); + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.resolveProperties(clientConf)) { + new ModuleParallelDeployHelper().deployArtifacts(artifactoryManager, deployableArtifactsByModule, clientConf.publisher.getPublishForkCount()); } } if (isPublishBuildInfo(clientConf, wereThereTestFailures)) { @@ -94,9 +94,9 @@ public void deploy( Build build, } private void publishBuildInfo(ArtifactoryClientConfiguration clientConf, Build build) { - try (ArtifactoryBuildInfoClient client = buildInfoClientBuilder.resolveProperties(clientConf)) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.resolveProperties(clientConf)) { logger.info("Artifactory Build Info Recorder: Deploying build info ..."); - Utils.sendBuildAndBuildRetention(client, build, clientConf); + Utils.sendBuildAndBuildRetention(artifactoryManager, build, clientConf); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/build-info-extractor-maven3/src/main/resources/META-INF/plexus/components.xml b/build-info-extractor-maven3/src/main/resources/META-INF/plexus/components.xml index cd2977c9b..1f5da9eaf 100644 --- a/build-info-extractor-maven3/src/main/resources/META-INF/plexus/components.xml +++ b/build-info-extractor-maven3/src/main/resources/META-INF/plexus/components.xml @@ -508,8 +508,8 @@ - org.jfrog.build.extractor.maven.BuildInfoClientBuilder - org.jfrog.build.extractor.maven.BuildInfoClientBuilder + org.jfrog.build.extractor.maven.ArtifactoryManagerBuilder + org.jfrog.build.extractor.maven.ArtifactoryManagerBuilder default false @@ -545,9 +545,9 @@ logger - org.jfrog.build.extractor.maven.BuildInfoClientBuilder + org.jfrog.build.extractor.maven.ArtifactoryManagerBuilder default - buildInfoClientBuilder + artifactoryManagerBuilder diff --git a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractor.java b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractor.java index c423fbc60..42da40492 100644 --- a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractor.java +++ b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractor.java @@ -10,10 +10,8 @@ import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ProxyConfiguration; import org.jfrog.build.extractor.BuildInfoExtractor; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.npm.NpmDriver; import org.jfrog.build.extractor.npm.types.NpmPackageInfo; import org.jfrog.build.extractor.npm.types.NpmProject; @@ -42,8 +40,7 @@ public class NpmBuildInfoExtractor implements BuildInfoExtractor { private static final String NPMRC_BACKUP_FILE_NAME = "jfrog.npmrc.backup"; private static final String NPMRC_FILE_NAME = ".npmrc"; - private ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; - private ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; + private final ArtifactoryManagerBuilder artifactoryManagerBuilder; private NpmPackageInfo npmPackageInfo = new NpmPackageInfo(); private TypeRestriction typeRestriction; private NpmDriver npmDriver; @@ -55,10 +52,9 @@ public class NpmBuildInfoExtractor implements BuildInfoExtractor { private String module; private Log logger; - NpmBuildInfoExtractor(ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, + NpmBuildInfoExtractor(ArtifactoryManagerBuilder artifactoryManagerBuilder, NpmDriver npmDriver, Log logger, String module, String buildName, String project) { - this.dependenciesClientBuilder = dependenciesClientBuilder; - this.buildInfoClientBuilder = buildInfoClientBuilder; + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.npmDriver = npmDriver; this.logger = logger; this.module = module; @@ -90,29 +86,29 @@ public Build extract(NpmProject npmProject) throws Exception { } private void preparePrerequisites(String resolutionRepository, Path workingDir) throws IOException { - try (ArtifactoryDependenciesClient dependenciesClient = dependenciesClientBuilder.build()) { - setNpmAuth(dependenciesClient); - setRegistryUrl(dependenciesClient, resolutionRepository); - setNpmProxy(dependenciesClient); + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + setNpmAuth(artifactoryManager); + setRegistryUrl(artifactoryManager, resolutionRepository); + setNpmProxy(artifactoryManager); } readPackageInfoFromPackageJson(workingDir); backupProjectNpmrc(workingDir); } - private void setNpmAuth(ArtifactoryDependenciesClient dependenciesClient) throws IOException { - npmAuth = dependenciesClient.getNpmAuth(); + private void setNpmAuth(ArtifactoryManager artifactoryManage) throws IOException { + npmAuth = artifactoryManage.getNpmAuth(); } - private void setRegistryUrl(ArtifactoryDependenciesClient dependenciesClient, String resolutionRepository) { - npmRegistry = dependenciesClient.getArtifactoryUrl(); + private void setRegistryUrl(ArtifactoryManager artifactoryManage, String resolutionRepository) { + npmRegistry = artifactoryManage.getUrl(); if (!StringUtils.endsWith(npmRegistry, "/")) { npmRegistry += "/"; } npmRegistry += "api/npm/" + resolutionRepository; } - private void setNpmProxy(ArtifactoryDependenciesClient dependenciesClient) { - ProxyConfiguration proxyConfiguration = dependenciesClient.getProxyConfiguration(); + private void setNpmProxy(ArtifactoryManager artifactoryManage) { + ProxyConfiguration proxyConfiguration = artifactoryManage.getProxyConfiguration(); if (proxyConfiguration == null || StringUtils.isBlank(proxyConfiguration.host)) { return; } @@ -340,14 +336,14 @@ private void populateDependenciesMap(Map dependencies, Map badPackages = Collections.synchronizedSet(new HashSet<>()); DefaultMutableTreeNode rootNode = NpmDependencyTree.createDependencyTree(npmDependencyTree, scope); - try (ArtifactoryDependenciesClient dependenciesClient = dependenciesClientBuilder.build()) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { // Create producer Runnable. ProducerRunnableBase[] producerRunnable = new ProducerRunnableBase[]{new NpmExtractorProducer(rootNode)}; // Create consumer Runnables. ConsumerRunnableBase[] consumerRunnables = new ConsumerRunnableBase[]{ - new NpmExtractorConsumer(dependenciesClient, dependencies, previousBuildDependencies, badPackages), - new NpmExtractorConsumer(dependenciesClient, dependencies, previousBuildDependencies, badPackages), - new NpmExtractorConsumer(dependenciesClient, dependencies, previousBuildDependencies, badPackages) + new NpmExtractorConsumer(artifactoryManager, dependencies, previousBuildDependencies, badPackages), + new NpmExtractorConsumer(artifactoryManager, dependencies, previousBuildDependencies, badPackages), + new NpmExtractorConsumer(artifactoryManager, dependencies, previousBuildDependencies, badPackages) }; // Create the deployment executor. ProducerConsumerExecutor deploymentExecutor = new ProducerConsumerExecutor(logger, producerRunnable, consumerRunnables, CONNECTION_POOL_SIZE); @@ -365,9 +361,9 @@ private Map getDependenciesMapFromLatestBuild() throws IOExc if (StringUtils.isBlank(buildName)) { return Collections.emptyMap(); } - try (ArtifactoryBuildInfoClient buildInfoClient = buildInfoClientBuilder.build()) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { // Get previous build's dependencies. - Build previousBuildInfo = buildInfoClient.getBuildInfo(buildName, "LATEST", project); + Build previousBuildInfo = artifactoryManager.getBuildInfo(buildName, "LATEST", project); if (previousBuildInfo == null) { return Collections.emptyMap(); } diff --git a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmCommand.java b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmCommand.java index eaf1c834a..4855ffe16 100644 --- a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmCommand.java +++ b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmCommand.java @@ -2,8 +2,8 @@ import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ArtifactoryVersion; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientBuilderBase; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.npm.NpmDriver; import org.jfrog.build.extractor.npm.types.NpmPackageInfo; import org.jfrog.build.extractor.packageManager.PackageManagerExtractor; @@ -26,16 +26,16 @@ abstract class NpmCommand extends PackageManagerExtractor { private static final ArtifactoryVersion MIN_SUPPORTED_NPM_VERSION = new ArtifactoryVersion("5.4.0"); NpmPackageInfo npmPackageInfo = new NpmPackageInfo(); - ArtifactoryClientBuilderBase clientBuilder; - ArtifactoryBaseClient client; + ArtifactoryManagerBuilder artifactoryManagerBuilder; + ArtifactoryManager artifactoryManager; NpmDriver npmDriver; Path workingDir; String repo; Log logger; Path path; - NpmCommand(ArtifactoryClientBuilderBase clientBuilder, String repo, Log logger, Path path, Map env) { - this.clientBuilder = clientBuilder; + NpmCommand(ArtifactoryManagerBuilder artifactoryManagerBuilder, String repo, Log logger, Path path, Map env) { + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.npmDriver = new NpmDriver(env); this.workingDir = Files.isDirectory(path) ? path : path.toAbsolutePath().getParent(); this.repo = repo; @@ -49,8 +49,8 @@ void validatePath() throws IOException { } } - void validateArtifactoryVersion() throws VersionException { - ArtifactoryVersion version = client.getArtifactoryVersion(); + void validateArtifactoryVersion() throws VersionException, IOException { + ArtifactoryVersion version = artifactoryManager.getVersion(); if (version.isNotFound()) { String message = "Couldn't execute npm task. Check connection with Artifactory."; throw new VersionException(message, VersionCompatibilityType.NOT_FOUND); diff --git a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorConsumer.java b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorConsumer.java index cb61d9850..8486f489d 100644 --- a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorConsumer.java +++ b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorConsumer.java @@ -6,7 +6,7 @@ import org.jfrog.build.api.producerConsumer.ProducerConsumerItem; import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.npm.types.NpmPackageInfo; import org.jfrog.build.extractor.producerConsumer.ConsumerRunnableBase; import org.jfrog.build.extractor.producerConsumer.ProducerConsumerExecutor; @@ -28,15 +28,15 @@ public class NpmExtractorConsumer extends ConsumerRunnableBase { "\"@npm.version\": \"%s\"" + "}).include(\"name\", \"repo\", \"path\", \"actual_sha1\", \"actual_md5\")"; private Map previousBuildDependencies; - private ArtifactoryDependenciesClient client; + private final ArtifactoryManager artifactoryManager; private Map dependencies; private ProducerConsumerExecutor executor; private Set badPackages; private Log log; - NpmExtractorConsumer(ArtifactoryDependenciesClient client, Map dependencies, + NpmExtractorConsumer(ArtifactoryManager artifactoryManager, Map dependencies, Map previousBuildDependencies, Set badPackages) { - this.client = client; + this.artifactoryManager = artifactoryManager; this.dependencies = dependencies; this.previousBuildDependencies = previousBuildDependencies; this.badPackages = badPackages; @@ -114,7 +114,7 @@ private Dependency createDependencyFromAqlResult(NpmPackageInfo npmPackageInfo, String aql = String.format(NPM_AQL_FORMAT, npmPackageInfo.getName(), npmPackageInfo.getVersion()); AqlSearchResult searchResult; try { - searchResult = client.searchArtifactsByAql(aql); + searchResult = artifactoryManager.searchArtifactsByAql(aql); if (searchResult.getResults().isEmpty()) { return null; } diff --git a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmInstallCi.java b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmInstallCi.java index 57f39af84..5847eadbb 100644 --- a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmInstallCi.java +++ b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmInstallCi.java @@ -4,10 +4,9 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.jfrog.build.api.Build; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.npm.types.NpmProject; import java.nio.file.Path; @@ -32,8 +31,7 @@ public class NpmInstallCi extends NpmCommand { /** * Run npm install or npm ci commands. * - * @param dependenciesClientBuilder - Dependencies client builder. - * @param buildInfoClientBuilder - Build Info client builder. + * @param artifactoryManagerBuilder - ArtifactoryManagerBuilder. * @param resolutionRepository - The repository it'll resolve from. * @param commandArgs - Npm command args. * @param buildName - The build's name. @@ -42,30 +40,13 @@ public class NpmInstallCi extends NpmCommand { * @param path - Path to directory contains package.json or path to '.tgz' file. * @param env - Environment variables to use during npm execution. */ - public NpmInstallCi(ArtifactoryDependenciesClientBuilder dependenciesClientBuilder, ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder, String resolutionRepository, String commandArgs, Log logger, Path path, Map env, String module, String buildName, boolean isCiCommand, String project) { - super(dependenciesClientBuilder, resolutionRepository, logger, path, env); - buildInfoExtractor = new NpmBuildInfoExtractor(dependenciesClientBuilder, buildInfoClientBuilder, npmDriver, logger, module, buildName, project); + public NpmInstallCi(ArtifactoryManagerBuilder artifactoryManagerBuilder, String resolutionRepository, String commandArgs, Log logger, Path path, Map env, String module, String buildName, boolean isCiCommand, String project) { + super(artifactoryManagerBuilder, resolutionRepository, logger, path, env); + buildInfoExtractor = new NpmBuildInfoExtractor(artifactoryManagerBuilder, npmDriver, logger, module, buildName, project); this.commandArgs = StringUtils.isBlank(commandArgs) ? new ArrayList<>() : Arrays.asList(commandArgs.trim().split("\\s+")); this.isCiCommand = isCiCommand; } - @Override - public Build execute() { - try (ArtifactoryDependenciesClient dependenciesClient = (ArtifactoryDependenciesClient) clientBuilder.build()) { - client = dependenciesClient; - validatePath(); - validateArtifactoryVersion(); - validateNpmVersion(); - validateRepoExists(client, repo, "Source repo must be specified"); - - NpmProject npmProject = new NpmProject(commandArgs, repo, workingDir, isCiCommand); - return buildInfoExtractor.extract(npmProject); - } catch (Exception e) { - logger.error(e.getMessage(), e); - throw new RuntimeException(e); - } - } - /** * Allow running npm install using a new Java process. * Used only in Jenkins to allow running 'rtNpm install' in a docker container. @@ -73,12 +54,10 @@ public Build execute() { public static void main(String[] ignored) { try { ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); - ArtifactoryDependenciesClientBuilder dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); - ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); + ArtifactoryManagerBuilder artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); ArtifactoryClientConfiguration.PackageManagerHandler packageManagerHandler = clientConfiguration.packageManagerHandler; ArtifactoryClientConfiguration.NpmHandler npmHandler = clientConfiguration.npmHandler; - NpmInstallCi npmInstall = new NpmInstallCi(dependenciesClientBuilder, - buildInfoClientBuilder, + NpmInstallCi npmInstall = new NpmInstallCi(artifactoryManagerBuilder, clientConfiguration.resolver.getRepoKey(), packageManagerHandler.getArgs(), clientConfiguration.getLog(), @@ -94,4 +73,21 @@ public static void main(String[] ignored) { System.exit(1); } } + + @Override + public Build execute() { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + this.artifactoryManager = artifactoryManager; + validatePath(); + validateArtifactoryVersion(); + validateNpmVersion(); + validateRepoExists(artifactoryManager, repo, "Source repo must be specified"); + + NpmProject npmProject = new NpmProject(commandArgs, repo, workingDir, isCiCommand); + return buildInfoExtractor.extract(npmProject); + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException(e); + } + } } diff --git a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmPublish.java b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmPublish.java index 9f653ea8f..c48aaea5d 100644 --- a/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmPublish.java +++ b/build-info-extractor-npm/src/main/java/org/jfrog/build/extractor/npm/extractor/NpmPublish.java @@ -14,9 +14,9 @@ import org.jfrog.build.api.builder.ModuleType; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ArtifactoryUploadResponse; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.util.VersionException; @@ -46,23 +46,46 @@ public class NpmPublish extends NpmCommand { /** * Publish npm package. * - * @param clientBuilder - Build Info client builder. - * @param properties - The Artifact properties to set (Build name, Build number, etc...). - * @param path - Path to directory contains package.json or path to '.tgz' file. - * @param deploymentRepository - The repository it'll deploy to. - * @param logger - The logger. - * @param env - Environment variables to use during npm execution. + * @param artifactoryManagerBuilder - Artifactory manager builder builder. + * @param properties - The Artifact properties to set (Build name, Build number, etc...). + * @param path - Path to directory contains package.json or path to '.tgz' file. + * @param deploymentRepository - The repository it'll deploy to. + * @param logger - The logger. + * @param env - Environment variables to use during npm execution. */ - public NpmPublish(ArtifactoryBuildInfoClientBuilder clientBuilder, ArrayListMultimap properties, Path path, String deploymentRepository, Log logger, Map env, String module) { - super(clientBuilder, deploymentRepository, logger, path, env); + public NpmPublish(ArtifactoryManagerBuilder artifactoryManagerBuilder, ArrayListMultimap properties, Path path, String deploymentRepository, Log logger, Map env, String module) { + super(artifactoryManagerBuilder, deploymentRepository, logger, path, env); this.properties = properties; this.module = module; } + /** + * Allow running npm publish using a new Java process. + * Used only in Jenkins to allow running 'rtNpm publish' in a docker container. + */ + public static void main(String[] ignored) { + try { + ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); + ArtifactoryManagerBuilder artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.publisher); + ArtifactoryClientConfiguration.PackageManagerHandler npmHandler = clientConfiguration.packageManagerHandler; + NpmPublish npmPublish = new NpmPublish(artifactoryManagerBuilder, + ArrayListMultimap.create(clientConfiguration.publisher.getMatrixParams().asMultimap()), + Paths.get(npmHandler.getPath() != null ? npmHandler.getPath() : "."), + clientConfiguration.publisher.getRepoKey(), + clientConfiguration.getLog(), + clientConfiguration.getAllProperties(), + npmHandler.getModule()); + npmPublish.executeAndSaveBuildInfo(clientConfiguration); + } catch (RuntimeException e) { + ExceptionUtils.printRootCauseStackTrace(e, System.out); + System.exit(1); + } + } + @Override public Build execute() { - try (ArtifactoryBuildInfoClient dependenciesClient = (ArtifactoryBuildInfoClient) clientBuilder.build()) { - client = dependenciesClient; + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + this.artifactoryManager = artifactoryManager; preparePrerequisites(); if (!tarballProvided) { pack(); @@ -78,13 +101,6 @@ public Build execute() { } } - private void preparePrerequisites() throws InterruptedException, VersionException, IOException { - validateArtifactoryVersion(); - validateNpmVersion(); - validateRepoExists(client, repo, "Target repo must be specified"); - setPackageInfo(); - } - private void setPackageInfo() throws IOException { if (Files.isDirectory(path)) { try (FileInputStream fis = new FileInputStream(path.resolve("package.json").toFile())) { @@ -124,22 +140,11 @@ private void deploy() throws IOException { doDeploy(); } - private void doDeploy() throws IOException { - DeployDetails deployDetails = new DeployDetails.Builder() - .file(path.toFile()) - .targetRepository(repo) - .addProperties(properties) - .artifactPath(npmPackageInfo.getDeployPath()) - .packageType(DeployDetails.PackageType.NPM) - .build(); - - ArtifactoryUploadResponse response = ((ArtifactoryBuildInfoClient) client).deployArtifact(deployDetails); - - deployedArtifact = new ArtifactBuilder(npmPackageInfo.getModuleId()) - .md5(response.getChecksums().getMd5()) - .sha1(response.getChecksums().getSha1()) - .remotePath(StringUtils.substringBeforeLast(npmPackageInfo.getDeployPath(), "/")) - .build(); + private void preparePrerequisites() throws InterruptedException, VersionException, IOException { + validateArtifactoryVersion(); + validateNpmVersion(); + validateRepoExists(artifactoryManager, repo, "Target repo must be specified"); + setPackageInfo(); } private void deleteCreatedTarball() throws IOException { @@ -156,26 +161,21 @@ private Build createBuild() { return build; } - /** - * Allow running npm publish using a new Java process. - * Used only in Jenkins to allow running 'rtNpm publish' in a docker container. - */ - public static void main(String[] ignored) { - try { - ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); - ArtifactoryBuildInfoClientBuilder clientBuilder = new ArtifactoryBuildInfoClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.publisher); - ArtifactoryClientConfiguration.PackageManagerHandler npmHandler = clientConfiguration.packageManagerHandler; - NpmPublish npmPublish = new NpmPublish(clientBuilder, - ArrayListMultimap.create(clientConfiguration.publisher.getMatrixParams().asMultimap()), - Paths.get(npmHandler.getPath() != null ? npmHandler.getPath() : "."), - clientConfiguration.publisher.getRepoKey(), - clientConfiguration.getLog(), - clientConfiguration.getAllProperties(), - npmHandler.getModule()); - npmPublish.executeAndSaveBuildInfo(clientConfiguration); - } catch (RuntimeException e) { - ExceptionUtils.printRootCauseStackTrace(e, System.out); - System.exit(1); - } + private void doDeploy() throws IOException { + DeployDetails deployDetails = new DeployDetails.Builder() + .file(path.toFile()) + .targetRepository(repo) + .addProperties(properties) + .artifactPath(npmPackageInfo.getDeployPath()) + .packageType(DeployDetails.PackageType.NPM) + .build(); + + ArtifactoryUploadResponse response = artifactoryManager.upload(deployDetails); + + deployedArtifact = new ArtifactBuilder(npmPackageInfo.getModuleId()) + .md5(response.getChecksums().getMd5()) + .sha1(response.getChecksums().getSha1()) + .remotePath(StringUtils.substringBeforeLast(npmPackageInfo.getDeployPath(), "/")) + .build(); } } diff --git a/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractorTest.java b/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractorTest.java index 5c72e08a0..9d190abf4 100644 --- a/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractorTest.java +++ b/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmBuildInfoExtractorTest.java @@ -96,7 +96,7 @@ private Object[][] setTypeRestrictionProvider() { @Test(dataProvider = "setTypeRestrictionProvider") public void setTypeRestrictionTest(NpmBuildInfoExtractor.TypeRestriction expected, String[][] confs) { - NpmBuildInfoExtractor extractor = new NpmBuildInfoExtractor(null, null, null, null, null, null, null); + NpmBuildInfoExtractor extractor = new NpmBuildInfoExtractor(null, null, null, null, null, null); for (String[] conf : confs) { extractor.setTypeRestriction(conf[0], conf[1]); diff --git a/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorTest.java b/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorTest.java index 379fff4f5..08eabfc2f 100644 --- a/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorTest.java +++ b/build-info-extractor-npm/src/test/java/org/jfrog/build/extractor/npm/extractor/NpmExtractorTest.java @@ -10,8 +10,7 @@ import org.jfrog.build.api.Dependency; import org.jfrog.build.api.Module; import org.jfrog.build.api.builder.DependencyBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.clientConfiguration.util.DependenciesDownloaderHelper; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; @@ -47,7 +46,7 @@ public class NpmExtractorTest extends IntegrationTestsBase { private static final Path PROJECTS_ROOT = Paths.get(".").toAbsolutePath().normalize().resolve(Paths.get("src", "test", "resources", "org", "jfrog", "build", "extractor")); - private ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; private DependenciesDownloaderHelper downloaderHelper; public NpmExtractorTest() { @@ -116,9 +115,8 @@ private String getTargetPath() { @BeforeClass private void setUp() throws IOException { - dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); - buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); - downloaderHelper = new DependenciesDownloaderHelper(dependenciesClient, ".", log); + artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); + downloaderHelper = new DependenciesDownloaderHelper(artifactoryManager, ".", log); deployTestDependencies(Project.ASGARD, Project.MIDGARD, Project.ALFHEIM, Project.SVARTALFHEIM); } @@ -130,7 +128,7 @@ private void deployTestDependencies(Project... projects) throws IOException { .artifactPath(project.getTargetPath()) .packageType(DeployDetails.PackageType.NPM) .build(); - buildInfoClient.deployArtifact(deployDetails); + artifactoryManager.upload(deployDetails); } } @@ -188,15 +186,15 @@ private void runNpmTest(Project project, Dependency[] expectedDependencies, Stri Path path = packageJsonPath ? projectDir.resolve("package.json") : projectDir; if (isNpmCi) { // Run npm install to generate package-lock.json file. - new NpmInstallCi(dependenciesClientBuilder, buildInfoClientBuilder, virtualRepo, args, log, path, null, null, null, false, null).execute(); + new NpmInstallCi(artifactoryManagerBuilder, virtualRepo, args, log, path, null, null, null, false, null).execute(); } // Execute command. NpmInstallCi buildExecutor; if (isNpmCi) { - buildExecutor = new NpmInstallCi(dependenciesClientBuilder, buildInfoClientBuilder, virtualRepo, args, log, path, null, null, null, true, null); + buildExecutor = new NpmInstallCi(artifactoryManagerBuilder, virtualRepo, args, log, path, null, null, null, true, null); } else { - buildExecutor = new NpmInstallCi(dependenciesClientBuilder, buildInfoClientBuilder, virtualRepo, args, log, path, null, null, null, false, null); + buildExecutor = new NpmInstallCi(artifactoryManagerBuilder, virtualRepo, args, log, path, null, null, null, false, null); } Build build = buildExecutor.execute(); @@ -235,7 +233,7 @@ public void npmPublishTest(Project project, ArrayListMultimap pr // Run npm publish projectDir = createProjectDir(project); Path path = StringUtils.isNotBlank(packageName) ? projectDir.resolve(packageName) : projectDir; - NpmPublish npmPublish = new NpmPublish(buildInfoClientBuilder, props, path, virtualRepo, log, null, null); + NpmPublish npmPublish = new NpmPublish(artifactoryManagerBuilder, props, path, virtualRepo, log, null, null); Build build = npmPublish.execute(); assertEquals(build.getModules().size(), 1); Module module = build.getModules().get(0); @@ -248,7 +246,7 @@ public void npmPublishTest(Project project, ArrayListMultimap pr assertEquals(module.getArtifacts().get(0).getName(), project.getModuleId()); assertEquals(module.getArtifacts().get(0).getRemotePath(), project.getRemotePath()); - // Download the artifact and check for its properties + // DownloadBase the artifact and check for its properties StringJoiner propertiesBuilder = new StringJoiner(";"); props.entries().forEach(property -> propertiesBuilder.add(property.getKey() + "=" + property.getValue())); FileSpec fileSpec = new FileSpec(); diff --git a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/DotnetDriver.java b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/DotnetDriver.java index 80c69e9ac..3b06f9328 100644 --- a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/DotnetDriver.java +++ b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/DotnetDriver.java @@ -1,7 +1,7 @@ package org.jfrog.build.extractor.nuget.drivers; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.executor.CommandExecutor; import java.io.IOException; diff --git a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/NugetDriver.java b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/NugetDriver.java index 9b0e4b9cd..b058b7ac0 100644 --- a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/NugetDriver.java +++ b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/NugetDriver.java @@ -1,7 +1,7 @@ package org.jfrog.build.extractor.nuget.drivers; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.executor.CommandExecutor; import java.io.IOException; diff --git a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/ToolchainDriverBase.java b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/ToolchainDriverBase.java index 9128c8031..b9a26a126 100644 --- a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/ToolchainDriverBase.java +++ b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/drivers/ToolchainDriverBase.java @@ -2,8 +2,7 @@ import org.apache.http.client.utils.URIBuilder; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.executor.CommandExecutor; import org.jfrog.build.extractor.executor.CommandResults; @@ -63,8 +62,8 @@ public String help() throws IOException, InterruptedException { return runCommand(new String[]{"help"}, Collections.emptyList(), null, logger); } - public String buildNugetSourceUrl(ArtifactoryBaseClient client, String repo, String apiProtocol) throws Exception { - URL rtUrl = new URL(client.getArtifactoryUrl()); + public String buildNugetSourceUrl(ArtifactoryManager artifactoryManager, String repo, String apiProtocol) throws Exception { + URL rtUrl = new URL(artifactoryManager.getUrl()); String nugetApi = apiProtocol.equalsIgnoreCase(V3) ? ARTIFACTORY_NUGET_API_V3 : ARTIFACTORY_NUGET_API; URIBuilder sourceUrlBuilder = new URIBuilder() .setScheme(rtUrl.getProtocol()) diff --git a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/extractor/NugetRun.java b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/extractor/NugetRun.java index 536b1e5bd..81935674a 100644 --- a/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/extractor/NugetRun.java +++ b/build-info-extractor-nuget/src/main/java/org/jfrog/build/extractor/nuget/extractor/NugetRun.java @@ -12,8 +12,8 @@ import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.nuget.drivers.DotnetDriver; import org.jfrog.build.extractor.nuget.drivers.NugetDriver; import org.jfrog.build.extractor.nuget.drivers.ToolchainDriverBase; @@ -64,7 +64,7 @@ public class NugetRun extends PackageManagerExtractor { private static final long serialVersionUID = 1L; - private ArtifactoryDependenciesClientBuilder clientBuilder; + private final ArtifactoryManagerBuilder artifactoryManagerBuilder; private ToolchainDriverBase toolchainDriver; private Path workingDir; private Log logger; @@ -81,7 +81,7 @@ public class NugetRun extends PackageManagerExtractor { /** * Run NuGet. * - * @param clientBuilder - Build Info client builder. + * @param artifactoryManagerBuilder - ArtifactoryManager builder builder. * @param resolutionRepo - The repository it'll resolve from. * @param useDotnetCli - Boolean indicates if .Net cli will be used. * @param nugetCmdArgs - NuGet exec args. @@ -94,8 +94,8 @@ public class NugetRun extends PackageManagerExtractor { * @param apiProtocol - A string indicates which NuGet protocol should be used (V2/V3). */ - public NugetRun(ArtifactoryDependenciesClientBuilder clientBuilder, String resolutionRepo, boolean useDotnetCli, String nugetCmdArgs, Log logger, Path path, Map env, String module, String username, String password, String apiProtocol) { - this.clientBuilder = clientBuilder; + public NugetRun(ArtifactoryManagerBuilder artifactoryManagerBuilder, String resolutionRepo, boolean useDotnetCli, String nugetCmdArgs, Log logger, Path path, Map env, String module, String username, String password, String apiProtocol) { + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.toolchainDriver = useDotnetCli ? new DotnetDriver(env, path, logger) : new NugetDriver(env, path, logger); this.workingDir = Files.isDirectory(path) ? path : path.toAbsolutePath().getParent(); this.logger = logger; @@ -148,7 +148,7 @@ protected static List createAlternativeVersionForms(String originalVersi public static void main(String[] ignored) { try { ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); - ArtifactoryDependenciesClientBuilder clientBuilder = new ArtifactoryDependenciesClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); + ArtifactoryManagerBuilder clientBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); ArtifactoryClientConfiguration.PackageManagerHandler handler = clientConfiguration.packageManagerHandler; NugetRun nugetRun = new NugetRun(clientBuilder, clientConfiguration.resolver.getRepoKey(), @@ -188,9 +188,9 @@ public Build execute() { } private void prepareAndRunCmd() throws Exception { - try (ArtifactoryDependenciesClient artifactoryClient = clientBuilder.build()) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { List extraArgs = new ArrayList<>(); - File configFile = prepareConfig(artifactoryClient); + File configFile = prepareConfig(artifactoryManager); if (configFile != null) { String configPath = configFile.getAbsolutePath(); extraArgs = StringUtils.isBlank(configPath) ? null : Arrays.asList(toolchainDriver.getFlagSyntax(ToolchainDriverBase.CONFIG_FILE_FLAG), configPath); @@ -203,12 +203,12 @@ private void prepareAndRunCmd() throws Exception { * Writes a temporary NuGet configuration which will be used during the restore. * The resolution repository will be set as a source in the configuration. */ - private File prepareConfig(ArtifactoryDependenciesClient client) throws Exception { + private File prepareConfig(ArtifactoryManager artifactoryManager) throws Exception { File configFile = null; if (!nugetCmdArgs.contains(toolchainDriver.getFlagSyntax(ToolchainDriverBase.CONFIG_FILE_FLAG)) && !nugetCmdArgs.contains(toolchainDriver.getFlagSyntax(ToolchainDriverBase.SOURCE_FLAG))) { configFile = File.createTempFile(NUGET_CONFIG_FILE_PREFIX, null); configFile.deleteOnExit(); - addSourceToConfigFile(configFile.getAbsolutePath(), client, resolutionRepo, username, password, apiProtocol); + addSourceToConfigFile(configFile.getAbsolutePath(), artifactoryManager, resolutionRepo, username, password, apiProtocol); } return configFile; } @@ -217,7 +217,7 @@ private File prepareConfig(ArtifactoryDependenciesClient client) throws Exceptio * We will write a temporary NuGet configuration using a string formater in order to support NuGet v3 protocol. * Currently the NuGet configuration utility doesn't allow setting protocolVersion. */ - private void addSourceToConfigFile(String configPath, ArtifactoryDependenciesClient client, String repo, String username, String password, String apiProtocol) throws Exception{ + private void addSourceToConfigFile(String configPath, ArtifactoryManager client, String repo, String username, String password, String apiProtocol) throws Exception{ String sourceUrl = toolchainDriver.buildNugetSourceUrl(client, repo, apiProtocol); String protocolVersion = apiProtocol.substring(apiProtocol.length() - 1); String configFileText = String.format(CONFIG_FILE_FORMAT, sourceUrl, protocolVersion, username, password); diff --git a/build-info-extractor-nuget/src/test/java/org/jfrog/build/extractor/nuget/extractor/NugetExtractorTest.java b/build-info-extractor-nuget/src/test/java/org/jfrog/build/extractor/nuget/extractor/NugetExtractorTest.java index 42d2c0a5a..f3279df23 100644 --- a/build-info-extractor-nuget/src/test/java/org/jfrog/build/extractor/nuget/extractor/NugetExtractorTest.java +++ b/build-info-extractor-nuget/src/test/java/org/jfrog/build/extractor/nuget/extractor/NugetExtractorTest.java @@ -6,8 +6,7 @@ import org.jfrog.build.IntegrationTestsBase; import org.jfrog.build.api.Build; import org.jfrog.build.api.Module; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -34,7 +33,7 @@ public class NugetExtractorTest extends IntegrationTestsBase { private static final Path PROJECTS_ROOT = Paths.get(".").toAbsolutePath().normalize().resolve(Paths.get("src", "test", "resources", "org", "jfrog", "build", "extractor")); - private ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; private Map env = new HashMap<>(); public NugetExtractorTest() { @@ -64,9 +63,8 @@ private enum Project { } @BeforeClass - private void setUp() throws IOException { - dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); - buildInfoClientBuilder = new ArtifactoryBuildInfoClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); + private void setUp() { + artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); } Object[][] packagesConfigTestsInfo = new Object[][]{ @@ -96,7 +94,7 @@ public void nugetRunTest(Project project, String args, String moduleName, String try { // Run nuget restore install projectDir = createProjectDir(project); - NugetRun nugetRun = new NugetRun(dependenciesClientBuilder, remoteRepo, false, args, log, projectDir, env, moduleName, getUsername(), getPassword(), "v2"); + NugetRun nugetRun = new NugetRun(artifactoryManagerBuilder, remoteRepo, false, args, log, projectDir, env, moduleName, getUsername(), getPassword(), "v2"); executeAndAssertBuildInfo(nugetRun, expectedModules, expectedDependencies); } catch (Exception e) { fail(ExceptionUtils.getStackTrace(e)); @@ -118,7 +116,7 @@ public void dotnetCliRunTest(Project project, String args, String moduleName, St try { // Run nuget restore install projectDir = createProjectDir(project); - NugetRun nugetRun = new NugetRun(dependenciesClientBuilder, remoteRepo, true, args, log, projectDir, env, moduleName, getUsername(), getPassword(), "v2"); + NugetRun nugetRun = new NugetRun(artifactoryManagerBuilder, remoteRepo, true, args, log, projectDir, env, moduleName, getUsername(), getPassword(), "v2"); executeAndAssertBuildInfo(nugetRun, expectedModules, expectedDependencies); } catch (Exception e) { fail(ExceptionUtils.getStackTrace(e)); @@ -168,7 +166,7 @@ private Object[][] projectRootProvider() { private void getProjectRootTest(String args, String expectedProjectRootFileName) { try { File rootDir = PROJECTS_ROOT.resolve("projectRootTestDir").toFile(); - NugetRun nugetRun = new NugetRun(dependenciesClientBuilder, remoteRepo, false, args, log, rootDir.toPath(), env, null, getUsername(), getPassword(), "v2"); + NugetRun nugetRun = new NugetRun(artifactoryManagerBuilder, remoteRepo, false, args, log, rootDir.toPath(), env, null, getUsername(), getPassword(), "v2"); File projectRoot = nugetRun.getProjectRootPath(); assertTrue(projectRoot.getPath().endsWith(expectedProjectRootFileName)); } catch (Exception e) { diff --git a/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipBuildInfoExtractor.java b/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipBuildInfoExtractor.java index 3ce6a7f11..f59b9311b 100644 --- a/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipBuildInfoExtractor.java +++ b/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipBuildInfoExtractor.java @@ -9,7 +9,7 @@ import org.jfrog.build.api.builder.ModuleType; import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.IOException; import java.nio.file.Path; @@ -29,12 +29,12 @@ public class PipBuildInfoExtractor { private static final String PIP_AQL_FILE_PART = "{\"name\":\"%s\"},"; private static final int PIP_AQL_BULK_SIZE = 3; - Build extract(ArtifactoryDependenciesClient client, String repository, String installationLog, Path executionPath, String module, Log logger) throws IOException { + Build extract(ArtifactoryManager artifactoryManager, String repository, String installationLog, Path executionPath, String module, Log logger) throws IOException { // Parse logs and create dependency list of Map downloadedDependencies = PipLogParser.parse(installationLog, logger); // Create package-name to dependency map. - Map dependenciesMap = buildDependenciesMap(downloadedDependencies, client, repository, executionPath, logger); + Map dependenciesMap = buildDependenciesMap(downloadedDependencies, artifactoryManager, repository, executionPath, logger); // Create Build. List dependenciesList = new ArrayList<>(dependenciesMap.values()); @@ -46,14 +46,13 @@ Build extract(ArtifactoryDependenciesClient client, String repository, String in * Creation is based on the dependencies downloaded in this pip-install execution, and the cache saved in previous builds. * * @param downloadedDependencies - The dependencies of this pip-execution, package-name to downloaded package-file map. - * @param client - Artifactory client for fetching artifacts data. + * @param artifactoryManager - Artifactory manager for fetching artifacts data. * @param repository - Resolution repository. * @param executionPath - Path of pip command's execution. * @param logger - The logger. * @return Mapping of a package-name and its Dependency object. - * @throws IOException */ - Map buildDependenciesMap(Map downloadedDependencies, ArtifactoryDependenciesClient client, String repository, Path executionPath, Log logger) throws IOException { + Map buildDependenciesMap(Map downloadedDependencies, ArtifactoryManager artifactoryManager, String repository, Path executionPath, Log logger) throws IOException { Map dependenciesMap = new HashMap<>(); DependenciesCache dependenciesCache = DependenciesCache.getProjectDependenciesCache(executionPath, logger); @@ -73,7 +72,7 @@ Map buildDependenciesMap(Map downloadedDepen } // Get dependencies from Artifactory. - dependenciesMap.putAll(getDependenciesFromArtifactory(getFromArtifactoryMap, repository, client, logger)); + dependenciesMap.putAll(getDependenciesFromArtifactory(getFromArtifactoryMap, repository, artifactoryManager, logger)); // Prompt missing dependencies. Set missingDeps = downloadedDependencies.keySet().stream() @@ -91,17 +90,16 @@ Map buildDependenciesMap(Map downloadedDepen * * @param fileToPackageMap - Mapping between a downloaded file to its package name. * @param repository - Resolution repository. - * @param client - Artifactory client for fetching artifacts data. + * @param artifactoryManager - Artifactory manager for fetching artifacts data. * @param logger - The logger. * @return Mapping of a package-name and its Dependency object. - * @throws IOException */ private Map getDependenciesFromArtifactory(Map fileToPackageMap, String repository, - ArtifactoryDependenciesClient client, Log logger) throws IOException { + ArtifactoryManager artifactoryManager, Log logger) throws IOException { if (fileToPackageMap.isEmpty()) { return Collections.emptyMap(); } - AqlSearchResult searchResult = runAqlQueries(createAqlQueries(fileToPackageMap, repository, PIP_AQL_BULK_SIZE), client); + AqlSearchResult searchResult = runAqlQueries(createAqlQueries(fileToPackageMap, repository, PIP_AQL_BULK_SIZE), artifactoryManager); return createDependenciesFromAqlResult(searchResult, fileToPackageMap, logger); } @@ -129,11 +127,11 @@ static String getPipDependenciesAql(StringBuilder filesQueryPartBuilder, String return String.format(PIP_AQL_FORMAT, repository, filesQueryPartBuilder.toString()); } - private AqlSearchResult runAqlQueries(List aqlQueries, ArtifactoryDependenciesClient client) throws IOException { + private AqlSearchResult runAqlQueries(List aqlQueries, ArtifactoryManager artifactoryManager) throws IOException { AqlSearchResult aggregatedResults = new AqlSearchResult(); for (String aql : aqlQueries) { try { - AqlSearchResult searchResult = client.searchArtifactsByAql(aql); + AqlSearchResult searchResult = artifactoryManager.searchArtifactsByAql(aql); if (!searchResult.getResults().isEmpty()) { aggregatedResults.getResults().addAll(searchResult.getResults()); } diff --git a/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipInstall.java b/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipInstall.java index 68c86f2d5..457a1f326 100644 --- a/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipInstall.java +++ b/build-info-extractor-pip/src/main/java/org/jfrog/build/extractor/pip/extractor/PipInstall.java @@ -4,10 +4,9 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.jfrog.build.api.Build; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientBuilderBase; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.packageManager.PackageManagerExtractor; import org.jfrog.build.extractor.packageManager.PackageManagerUtils; import org.jfrog.build.extractor.pip.PipDriver; @@ -31,7 +30,7 @@ public class PipInstall extends PackageManagerExtractor { private static final String ARTIFACTORY_PIP_API_START = "/api/pypi/"; private static final String ARTIFACTORY_PIP_API_END = "/simple"; - private ArtifactoryClientBuilderBase clientBuilder; + private final ArtifactoryManagerBuilder artifactoryManagerBuilder; private PipDriver pipDriver; private Path workingDir; private String repo; @@ -42,9 +41,9 @@ public class PipInstall extends PackageManagerExtractor { private String password; private String module; - public PipInstall(ArtifactoryDependenciesClientBuilder clientBuilder, String resolutionRepository, String installArgs, Log logger, Path path, Map env, String module, String username, String password, String envActivation) { + public PipInstall(ArtifactoryManagerBuilder artifactoryManagerBuilder, String resolutionRepository, String installArgs, Log logger, Path path, Map env, String module, String username, String password, String envActivation) { - this.clientBuilder = clientBuilder; + this.artifactoryManagerBuilder = artifactoryManagerBuilder; this.path = path; this.logger = logger; this.repo = resolutionRepository; @@ -64,28 +63,6 @@ public PipInstall(ArtifactoryDependenciesClientBuilder clientBuilder, String res : module; } - public Build execute() { - try (ArtifactoryDependenciesClient dependenciesClient = (ArtifactoryDependenciesClient) clientBuilder.build()) { - validateRepoExists(dependenciesClient, repo, "Source repo must be specified"); - String artifactoryUrlWithCredentials = PackageManagerUtils.createArtifactoryUrlWithCredentials(dependenciesClient.getArtifactoryUrl(), username, password, ARTIFACTORY_PIP_API_START + repo + ARTIFACTORY_PIP_API_END); - - // Run pip install with URL and get output. - String installLog = pipDriver.install(path.toFile(), artifactoryUrlWithCredentials, installArgs, logger); - logger.info(installLog); - - // Parse output and get all dependencies. - PipBuildInfoExtractor buildInfoExtractor = new PipBuildInfoExtractor(); - try { - return buildInfoExtractor.extract(dependenciesClient, repo, installLog, path, module, logger); - } catch (IOException e) { - throw new IOException("Build info collection failed", e); - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - throw new RuntimeException(e); - } - } - /** * Allow running pip install using a new Java process. * Used only in Jenkins to allow running 'rtPip install' in a docker container. @@ -93,9 +70,9 @@ public Build execute() { public static void main(String[] ignored) { try { ArtifactoryClientConfiguration clientConfiguration = createArtifactoryClientConfiguration(); - ArtifactoryDependenciesClientBuilder clientBuilder = new ArtifactoryDependenciesClientBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); + ArtifactoryManagerBuilder artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setClientConfiguration(clientConfiguration, clientConfiguration.resolver); ArtifactoryClientConfiguration.PackageManagerHandler pipHandler = clientConfiguration.packageManagerHandler; - PipInstall pipInstall = new PipInstall(clientBuilder, + PipInstall pipInstall = new PipInstall(artifactoryManagerBuilder, clientConfiguration.resolver.getRepoKey(), pipHandler.getArgs(), clientConfiguration.getLog(), @@ -111,4 +88,26 @@ public static void main(String[] ignored) { System.exit(1); } } + + public Build execute() { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { + validateRepoExists(artifactoryManager, repo, "Source repo must be specified"); + String artifactoryUrlWithCredentials = PackageManagerUtils.createArtifactoryUrlWithCredentials(artifactoryManager.getUrl(), username, password, ARTIFACTORY_PIP_API_START + repo + ARTIFACTORY_PIP_API_END); + + // Run pip install with URL and get output. + String installLog = pipDriver.install(path.toFile(), artifactoryUrlWithCredentials, installArgs, logger); + logger.info(installLog); + + // Parse output and get all dependencies. + PipBuildInfoExtractor buildInfoExtractor = new PipBuildInfoExtractor(); + try { + return buildInfoExtractor.extract(artifactoryManager, repo, installLog, path, module, logger); + } catch (IOException e) { + throw new IOException("Build info collection failed", e); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException(e); + } + } } diff --git a/build-info-extractor-pip/src/test/java/org/jfrog/build/extractor/pip/extractor/PipExtractorTest.java b/build-info-extractor-pip/src/test/java/org/jfrog/build/extractor/pip/extractor/PipExtractorTest.java index 9f08fa857..54d974c32 100644 --- a/build-info-extractor-pip/src/test/java/org/jfrog/build/extractor/pip/extractor/PipExtractorTest.java +++ b/build-info-extractor-pip/src/test/java/org/jfrog/build/extractor/pip/extractor/PipExtractorTest.java @@ -6,7 +6,7 @@ import org.jfrog.build.IntegrationTestsBase; import org.jfrog.build.api.Build; import org.jfrog.build.api.Module; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryDependenciesClientBuilder; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; import org.jfrog.build.extractor.pip.PipDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -34,7 +34,7 @@ public class PipExtractorTest extends IntegrationTestsBase { private static final Path PROJECTS_ROOT = Paths.get(".").toAbsolutePath().normalize().resolve(Paths.get("src", "test", "resources", "org", "jfrog", "build", "extractor")); - private ArtifactoryDependenciesClientBuilder dependenciesClientBuilder; + private ArtifactoryManagerBuilder artifactoryManagerBuilder; private String pipEnvVar; private PipDriver driver; private Map env; @@ -77,7 +77,7 @@ private enum Project { @BeforeClass private void setUp() { - dependenciesClientBuilder = new ArtifactoryDependenciesClientBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); + artifactoryManagerBuilder = new ArtifactoryManagerBuilder().setArtifactoryUrl(getUrl()).setUsername(getUsername()).setPassword(getPassword()).setLog(getLog()); // Read pip environment path variable. pipEnvVar = System.getenv(BITESTS_ARTIFACTORY_ENV_VAR_PREFIX + "PIP_ENV"); @@ -122,7 +122,7 @@ private void pipInstallTest(Project project) { } // Run pip-install. - PipInstall pipInstall = new PipInstall(dependenciesClientBuilder, virtualRepo, project.args, getLog(),projectDir, env, project.moduleId, getUsername(), getPassword(), null); + PipInstall pipInstall = new PipInstall(artifactoryManagerBuilder, virtualRepo, project.args, getLog(), projectDir, env, project.moduleId, getUsername(), getPassword(), null); Build build = pipInstall.execute(); assertNotNull(build, "Pip execution returned empty build."); diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/ModuleParallelDeployHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/ModuleParallelDeployHelper.java index ae4a73aef..289fbb682 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/ModuleParallelDeployHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/ModuleParallelDeployHelper.java @@ -1,6 +1,6 @@ package org.jfrog.build.extractor; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import java.io.IOException; @@ -19,10 +19,10 @@ public class ModuleParallelDeployHelper { public static final int DEFAULT_DEPLOYMENT_THREADS = 3; - public void deployArtifacts(ArtifactoryBuildInfoClient client, + public void deployArtifacts(ArtifactoryManager artifactoryManager, Map> deployableArtifactsByModule, int publishForkCount) { if (publishForkCount <= 1) { - deployableArtifactsByModule.forEach((module, deployableArtifacts) -> deploy(client, deployableArtifacts, null)); + deployableArtifactsByModule.forEach((module, deployableArtifacts) -> deploy(artifactoryManager, deployableArtifacts, null)); } else { try { ExecutorService executor = Executors.newFixedThreadPool(publishForkCount); @@ -30,7 +30,7 @@ public void deployArtifacts(ArtifactoryBuildInfoClient client, deployableArtifactsByModule.values().stream() .map(deployDetails -> CompletableFuture.runAsync(() -> - deploy(client, deployDetails, "[" + Thread.currentThread().getName() + "]"), executor)) + deploy(artifactoryManager, deployDetails, "[" + Thread.currentThread().getName() + "]"), executor)) .toArray(CompletableFuture[]::new)); allDeployments.get(); } catch (InterruptedException | ExecutionException e) { @@ -39,10 +39,10 @@ public void deployArtifacts(ArtifactoryBuildInfoClient client, } } - private void deploy(ArtifactoryBuildInfoClient client, Set deployableArtifacts, String logPrefix) { + private void deploy(ArtifactoryManager artifactoryManager, Set deployableArtifacts, String logPrefix) { deployableArtifacts.forEach(artifact -> { try { - client.deployArtifact(artifact, logPrefix); + artifactoryManager.upload(artifact, logPrefix); } catch (IOException e) { throw new RuntimeException("Error occurred while publishing artifact to Artifactory: " + artifact.getFile() + diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryBuildInfoClientBuilder.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryBuildInfoClientBuilder.java deleted file mode 100644 index a4820d996..000000000 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryBuildInfoClientBuilder.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jfrog.build.extractor.clientConfiguration; - -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; - -/** - * Created by Bar Belity on 10/10/2018. - */ -public class ArtifactoryBuildInfoClientBuilder extends ArtifactoryClientBuilderBase { - - @Override - public ArtifactoryBuildInfoClient build() { - ArtifactoryBuildInfoClient client = new ArtifactoryBuildInfoClient(artifactoryUrl, username, password, accessToken, log); - build(client); - return client; - } - - @Override - protected ArtifactoryBuildInfoClientBuilder self() { - return this; - } -} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryDependenciesClientBuilder.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryDependenciesClientBuilder.java deleted file mode 100644 index 604864071..000000000 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryDependenciesClientBuilder.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jfrog.build.extractor.clientConfiguration; - -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; - -/** - * @author Yahav Itzhak - */ -public class ArtifactoryDependenciesClientBuilder extends ArtifactoryClientBuilderBase { - - @Override - public ArtifactoryDependenciesClient build() { - ArtifactoryDependenciesClient client = new ArtifactoryDependenciesClient(artifactoryUrl, username, password, accessToken, log); - build(client); - return client; - } - - @Override - protected ArtifactoryDependenciesClientBuilder self() { - return this; - } -} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryManagerBuilder.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryManagerBuilder.java new file mode 100644 index 000000000..dc2648a0a --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryManagerBuilder.java @@ -0,0 +1,21 @@ +package org.jfrog.build.extractor.clientConfiguration; + +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; + +/** + * Created by Bar Belity on 10/10/2018. + */ +public class ArtifactoryManagerBuilder extends ManagerBuilderBase { + + @Override + public ArtifactoryManager build() { + ArtifactoryManager client = new ArtifactoryManager(artifactoryUrl, username, password, accessToken, log); + build(client); + return client; + } + + @Override + protected ArtifactoryManagerBuilder self() { + return this; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryClientBuilderBase.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ManagerBuilderBase.java similarity index 91% rename from build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryClientBuilderBase.java rename to build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ManagerBuilderBase.java index 25b121259..9767da697 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ArtifactoryClientBuilderBase.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/ManagerBuilderBase.java @@ -3,7 +3,8 @@ import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ProxyConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient; +import org.jfrog.build.extractor.clientConfiguration.client.ManagerBase; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import javax.net.ssl.SSLContext; import java.io.Serializable; @@ -12,7 +13,7 @@ * @author Yahav Itzhak */ @SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue"}) -public abstract class ArtifactoryClientBuilderBase> implements Serializable { +public abstract class ManagerBuilderBase> implements Serializable { private static final long serialVersionUID = 1L; protected ProxyConfiguration proxyConfiguration; @@ -105,7 +106,7 @@ public T setClientConfiguration(ArtifactoryClientConfiguration clientConfigurati return self(); } - protected ArtifactoryBaseClient build(ArtifactoryBaseClient client) { + protected ArtifactoryManager build(ArtifactoryManager client) { if (proxyConfiguration != null) { client.setProxyConfiguration(proxyConfiguration.host, proxyConfiguration.port, @@ -125,7 +126,7 @@ protected ArtifactoryBaseClient build(ArtifactoryBaseClient client) { return client; } - public abstract ArtifactoryBaseClient build(); + public abstract ManagerBase build(); protected abstract T self(); } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBaseClient.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBaseClient.java deleted file mode 100644 index 72cfa874a..000000000 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBaseClient.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.jfrog.build.extractor.clientConfiguration.client; - -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.util.EntityUtils; -import org.jfrog.build.api.util.Log; -import org.jfrog.build.client.ArtifactoryHttpClient; -import org.jfrog.build.client.ArtifactoryVersion; -import org.jfrog.build.client.ProxyConfiguration; - -import javax.net.ssl.SSLContext; -import java.io.IOException; - -/** - * Created by Tamirh on 21/04/2016. - */ -public abstract class ArtifactoryBaseClient implements AutoCloseable { - public static final String SHA1_HEADER_NAME = "X-Checksum-Sha1"; - public static final String MD5_HEADER_NAME = "X-Checksum-Md5"; - - private static final String API_REPOSITORIES = "/api/repositories"; - - protected String artifactoryUrl; - protected ArtifactoryHttpClient httpClient; - protected final Log log; - /** - * Version of Artifactory we work with. - */ - private ArtifactoryVersion artifactoryVersion; - - public ArtifactoryBaseClient(String artifactoryUrl, String username, String password, String accessToken, Log logger) { - this.artifactoryUrl = StringUtils.stripEnd(artifactoryUrl, "/"); - if (StringUtils.isNotEmpty(accessToken)) { - httpClient = new ArtifactoryHttpClient(this.artifactoryUrl, accessToken, logger); - } else { - httpClient = new ArtifactoryHttpClient(this.artifactoryUrl, username, password, logger); - } - this.log = logger; - } - - public ArtifactoryBaseClient(String artifactoryUrl, ArtifactoryHttpClient httpClient, Log logger) { - this.artifactoryUrl = StringUtils.stripEnd(artifactoryUrl, "/"); - this.httpClient = httpClient; - this.log = logger; - } - - @Override - public void close() { - if (httpClient != null) { - httpClient.close(); - } - } - - /** - * Network timeout in seconds to use both for connection establishment and for unanswered requests. - * - * @param connectionTimeout Timeout in seconds. - */ - public void setConnectionTimeout(int connectionTimeout) { - httpClient.setConnectionTimeout(connectionTimeout); - } - - /** - * Connection Retries to perform - * - * @param connectionRetries The number of max retries. - */ - public void setConnectionRetries(int connectionRetries) { - httpClient.setConnectionRetries(connectionRetries); - } - - /** - * Sets the proxy host and port. - * - * @param host Proxy host - * @param port Proxy port - */ - public void setProxyConfiguration(String host, int port) { - httpClient.setProxyConfiguration(host, port, null, null); - } - - /** - * Sets the proxy details. - * - * @param host Proxy host - * @param port Proxy port - * @param username Username to authenticate with the proxy - * @param password Password to authenticate with the proxy - */ - public void setProxyConfiguration(String host, int port, String username, String password) { - httpClient.setProxyConfiguration(host, port, username, password); - } - - /** - * Sets full proxy details. - * - * @param proxy Proxy instance {@link org.jfrog.build.client.ProxyConfiguration} - */ - public void setProxyConfiguration(ProxyConfiguration proxy) { - httpClient.setProxyConfiguration(proxy.host, proxy.port, proxy.username, proxy.password); - } - - public ProxyConfiguration getProxyConfiguration() { - return httpClient.getProxyConfiguration(); - } - - /** - * Log setter for the PreemptiveHttpClient for jobs like the Jenkins Generic job that uses NullLog by default. - * - * @param log Log instance - */ - public void setLog(Log log) { - httpClient.getHttpClient().setLog(log); - } - - public void setInsecureTls(boolean insecureTls) { - httpClient.setInsecureTls(insecureTls); - } - - public void setSslContext(SSLContext sslContext) { - httpClient.setSslContext(sslContext); - } - - public String getArtifactoryUrl() { - return artifactoryUrl; - } - - public ArtifactoryVersion getArtifactoryVersion() { - if (artifactoryVersion == null) { - try { - artifactoryVersion = httpClient.getVersion(); - } catch (IOException e) { - artifactoryVersion = ArtifactoryVersion.NOT_FOUND; - } - } - return artifactoryVersion; - } - - public boolean isRepoExist(String repo) throws IOException { - String fullItemUrl = artifactoryUrl + API_REPOSITORIES + "/" + repo; - String encodedUrl = ArtifactoryHttpClient.encodeUrl(fullItemUrl); - HttpRequestBase httpRequest = new HttpGet(encodedUrl); - try (CloseableHttpResponse httpResponse = httpClient.getHttpClient().execute(httpRequest)) { - EntityUtils.consumeQuietly(httpResponse.getEntity()); - StatusLine statusLine = httpResponse.getStatusLine(); - if (statusLine.getStatusCode() == HttpStatus.SC_BAD_REQUEST) { - return false; - } - } - return true; - } -} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClient.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClient.java deleted file mode 100644 index 3e08a3df0..000000000 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClient.java +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (C) 2011 JFrog Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jfrog.build.extractor.clientConfiguration.client; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.*; -import org.apache.http.entity.FileEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.protocol.HTTP; -import org.apache.http.util.EntityUtils; -import org.jfrog.build.api.Build; -import org.jfrog.build.api.BuildRetention; -import org.jfrog.build.api.release.Distribution; -import org.jfrog.build.api.release.Promotion; -import org.jfrog.build.api.util.CommonUtils; -import org.jfrog.build.api.util.FileChecksumCalculator; -import org.jfrog.build.api.util.Log; -import org.jfrog.build.client.*; -import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; -import org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils; -import org.jfrog.build.extractor.clientConfiguration.util.JsonSerializer; -import org.jfrog.build.extractor.usageReport.UsageReporter; -import org.jfrog.build.util.VersionCompatibilityType; -import org.jfrog.build.util.VersionException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.util.*; - -import static org.jfrog.build.client.ArtifactoryHttpClient.encodeUrl; -import static org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration.DEFAULT_MIN_CHECKSUM_DEPLOY_SIZE_KB; - -/** - * Artifactory client to perform build info related tasks. - * - * @author Yossi Shaul - */ -public class ArtifactoryBuildInfoClient extends ArtifactoryBaseClient implements AutoCloseable { - public static final String BUILD_BROWSE_URL = "/webapp/builds"; - public static final String BUILD_BROWSE_PLATFORM_URL = "/ui/builds"; - public static final String APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON = "application/vnd.org.jfrog.artifactory+json"; - public static final String APPLICATION_JSON = "application/json"; - public static final String ITEM_LAST_MODIFIED = "/api/storage/"; - private static final String LOCAL_REPOS_REST_URL = "/api/repositories?type=local"; - private static final String REMOTE_REPOS_REST_URL = "/api/repositories?type=remote"; - private static final String VIRTUAL_REPOS_REST_URL = "/api/repositories?type=virtual"; - private static final String PUSH_TO_BINTRAY_REST_URL = "/api/build/pushToBintray/"; - private static final String BUILD_REST_URL = "/api/build"; - private static final String BUILD_RETENTION_REST_URL = BUILD_REST_URL + "/retention/"; - private static final String BUILD_RETENTION_REST_ASYNC_PARAM = "?async="; - private static final String BUILD_PROJECT_PARAM = "?project="; - private static final String USAGE_API = "/api/system/usage"; - private static final ArtifactoryVersion USAGE_ARTIFACTORY_MIN_VERSION = new ArtifactoryVersion("6.9.0"); - - private int minChecksumDeploySizeKb = DEFAULT_MIN_CHECKSUM_DEPLOY_SIZE_KB; - - /** - * Creates a new client for the given Artifactory url. - * - * @param artifactoryUrl Artifactory url in the form of: protocol://host[:port]/contextPath - */ - public ArtifactoryBuildInfoClient(String artifactoryUrl, Log log) { - this(artifactoryUrl, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, log); - } - - /** - * Creates a new client for the given Artifactory url. - * - * @param artifactoryUrl Artifactory url in the form of: protocol://host[:port]/contextPath - * @param username Authentication username - * @param password Authentication password - */ - public ArtifactoryBuildInfoClient(String artifactoryUrl, String username, String password, String accessToken, Log log) { - super(artifactoryUrl, username, password, accessToken, log); - } - - public ArtifactoryBuildInfoClient(String artifactoryUrl, String username, String password, Log log) { - this(artifactoryUrl, username, password, StringUtils.EMPTY, log); - } - - // Returns the name of the build-info repository, corresponding to the project key sent. - // Returns an empty string, if the provided projectKey is empty. - public static String getProjectQueryParam(String project, String prefix) { - if (StringUtils.isNotEmpty(project)) { - return prefix + encodeUrl(project); - } - return ""; - } - - public static String getProjectQueryParam(String project) { - return getProjectQueryParam(project, BUILD_PROJECT_PARAM); - } - - /** - * Creates a build info link to the published build in JFrog platform (Artifactory V7) - * - * @param platformUrl Base platform URL - * @param buildName Build name of the published build - * @param buildNumber Build number of the published build - * @param timeStamp Timestamp (started date time in milliseconds) of the published build - * @return Link to the published build in JFrog platform e.g. https://myartifactory.com/ui/builds/gradle-cli/1/1619429119501/published - */ - public static String createBuildInfoUrl(String platformUrl, String buildName, String buildNumber, String timeStamp, String project) { - return String.format("%s/%s/%s/%s/%s", platformUrl + BUILD_BROWSE_PLATFORM_URL, encodeUrl(buildName), encodeUrl(buildNumber), timeStamp, "published" + getProjectQueryParam(project)); - } - - /** - * Creates a build info link to the published build in Artifactory (Artifactory V6 or below) - * - * @param artifactoryUrl Base Artifactory URL - * @param buildName Build name of the published build - * @param buildNumber Build number of the published build - * @return Link to the published build in Artifactory e.g. https://myartifactory.com/artifactory/webapp/builds/gradle-cli/1 - */ - public static String createBuildInfoUrl(String artifactoryUrl, String buildName, String buildNumber) { - return String.format("%s/%s/%s",artifactoryUrl + BUILD_BROWSE_URL, encodeUrl(buildName), encodeUrl(buildNumber)); - } - - /** - * @return A list of local repositories available for deployment. - * @throws IOException On any connection error - */ - public List getLocalRepositoriesKeys() throws IOException { - return getRepositoriesList(LOCAL_REPOS_REST_URL); - } - - /** - * Set min file size for checksum deployment. - * - * @param minChecksumDeploySizeKb - file size in KB - */ - public void setMinChecksumDeploySizeKb(int minChecksumDeploySizeKb) { - this.minChecksumDeploySizeKb = minChecksumDeploySizeKb; - } - - /** - * @return A list of local and cache repositories. - * @throws IOException On any connection error - */ - public List getLocalAndCacheRepositoriesKeys() throws IOException { - List localRepositoriesKeys = getLocalRepositoriesKeys(); - List remoteRepositories = getRemoteRepositoriesKeys(); - List cacheRepositories = CommonUtils.transformList(remoteRepositories, repoKey -> repoKey + "-cache"); - - return CommonUtils.concatLists(localRepositoriesKeys, cacheRepositories); - } - - /** - * @return A list of remote repositories. - * @throws IOException On any connection error - */ - public List getRemoteRepositoriesKeys() throws IOException { - return getRepositoriesList(REMOTE_REPOS_REST_URL); - } - - /** - * @return A list of virtual repositories available for resolution. - * @throws IOException On any connection error - */ - public List getVirtualRepositoryKeys() throws IOException { - return getRepositoriesList(VIRTUAL_REPOS_REST_URL); - } - - private List getRepositoriesList(String restUrl) throws IOException { - List repositories = new ArrayList<>(); - - String reposUrl = artifactoryUrl + restUrl; - log.debug("Requesting repositories list from: " + reposUrl); - try (PreemptiveHttpClient client = httpClient.getHttpClient(); - CloseableHttpResponse response = client.execute(new HttpGet(reposUrl))) { - StatusLine statusLine = response.getStatusLine(); - HttpEntity entity = response.getEntity(); - if (statusLine.getStatusCode() != HttpStatus.SC_OK) { - String message = httpClient.getMessageFromEntity(entity); - EntityUtils.consumeQuietly(entity); - throw new IOException("Failed to obtain list of repositories. Status code: " + statusLine.getStatusCode() + message); - } - if (entity == null) { - return repositories; - } - try (InputStream content = entity.getContent()) { - JsonParser parser = httpClient.createJsonParser(content); - JsonNode result = parser.readValueAsTree(); - log.debug("Repositories result = " + result); - for (JsonNode jsonNode : result) { - String repositoryKey = jsonNode.get("key").asText(); - repositories.add(repositoryKey); - } - } - } - return repositories; - } - - public void sendBuildInfo(String buildInfoJson, String project) throws IOException { - String url = String.format("%s%s%s", artifactoryUrl, BUILD_REST_URL, getProjectQueryParam(project)); - HttpPut httpPut = new HttpPut(url); - try { - log.info("Deploying build descriptor to: " + httpPut.getURI().toString()); - sendHttpEntityRequest(httpPut, buildInfoJson, APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON); - } catch (IOException e) { - throw new IOException("Failed to send build descriptor. " + e.getMessage(), e); - } - } - - public Build getBuildInfo(String buildName, String buildNumber, String project) throws IOException { - // Only If the value of the buildNumber sent is "LATEST" or "LAST_RELEASE", replace the value with a specific build number. - buildNumber = getLatestBuildNumberFromArtifactory(buildName, buildNumber, project); - if (buildNumber == null) { - return null; - } - - String url = String.format("%s%s/%s/%s%s", artifactoryUrl, BUILD_REST_URL, encodeUrl(buildName), encodeUrl(buildNumber), getProjectQueryParam(project)); - HttpGet httpGet = new HttpGet(url); - try (CloseableHttpResponse httpResponse = sendHttpRequest(httpGet, HttpStatus.SC_OK)) { - String buildInfoJson = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); - EntityUtils.consumeQuietly(httpResponse.getEntity()); - return getBuildFromJson(buildInfoJson); - } catch (IOException e) { - throw new IOException("Failed to get build info. " + e.getMessage(), e); - } - } - - private String getLatestBuildNumberFromArtifactory(String buildName, String buildNumber, String project) throws IOException { - ArtifactoryDependenciesClient dependenciesClient = new ArtifactoryDependenciesClient(artifactoryUrl, httpClient, log); - return dependenciesClient.getLatestBuildNumberFromArtifactory(buildName, buildNumber, project); - } - - public void sendBuildRetetion(BuildRetention buildRetention, String buildName, String project, boolean async) throws IOException { - String buildRetentionJson = toJsonString(buildRetention); - String url = artifactoryUrl + BUILD_RETENTION_REST_URL + buildName + BUILD_RETENTION_REST_ASYNC_PARAM + async + getProjectQueryParam(project,"&project="); - HttpPost httpPost = new HttpPost(url); - try { - log.info(createBuildRetentionLogMsg(buildRetention, async)); - log.debug(buildRetentionJson); - sendHttpEntityRequest(httpPost, buildRetentionJson, APPLICATION_JSON); - } catch (IOException e) { - log.error("Failed to execute build retention.", e); - throw new IOException("Failed to execute build retention: " + e.getMessage(), e); - } - } - - private String createBuildRetentionLogMsg(BuildRetention buildRetention, boolean async) { - StringBuilder strBuilder = new StringBuilder().append("Sending"); - - if (async) { - strBuilder.append(" async"); - } - - strBuilder.append(" request for build retention"); - - if (buildRetention.isDeleteBuildArtifacts()) { - strBuilder.append(", deleting build artifacts"); - } - - if (buildRetention.getCount() != -1) { - strBuilder.append(", max number of builds to store: ").append(buildRetention.getCount()); - } - - if (buildRetention.getMinimumBuildDate() != null) { - strBuilder.append(", min build date: ").append(buildRetention.getMinimumBuildDate()); - } - - if (!buildRetention.getBuildNumbersNotToBeDiscarded().isEmpty()) { - strBuilder.append(", build numbers not to be discarded: ").append(buildRetention.getBuildNumbersNotToBeDiscarded()); - } - strBuilder.append("."); - - return strBuilder.toString(); - } - - public void sendModuleInfo(Build build) throws IOException { - log.debug("Sending build info modules: " + build); - try { - String url = artifactoryUrl + BUILD_REST_URL + "/append/" + encodeUrl(build.getName()) + "/" + - encodeUrl(build.getNumber()); - HttpPost httpPost = new HttpPost(url); - String modulesAsJsonString = toJsonString(build.getModules()); - log.info("Deploying build descriptor to: " + httpPost.getURI().toString()); - sendHttpEntityRequest(httpPost, modulesAsJsonString, APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON); - } catch (Exception e) { - log.error("Could not build the build-info modules object.", e); - throw new IOException("Could not publish build-info modules: " + e.getMessage(), e); - } - } - - private void sendHttpEntityRequest(HttpEntityEnclosingRequestBase request, String content, String contentType) throws IOException { - StringEntity stringEntity = new StringEntity(content, "UTF-8"); - stringEntity.setContentType(contentType); - request.setEntity(stringEntity); - try (CloseableHttpResponse response = sendHttpRequest(request, HttpStatus.SC_CREATED, HttpStatus.SC_OK, HttpStatus.SC_NO_CONTENT)) { - EntityUtils.consumeQuietly(response.getEntity()); - } - } - - private CloseableHttpResponse sendHttpRequest(HttpUriRequest request, int... httpStatuses) throws IOException { - CloseableHttpResponse httpResponse = httpClient.getHttpClient().execute(request); - StatusLine statusLine = httpResponse.getStatusLine(); - for (int status : httpStatuses) { - if (statusLine.getStatusCode() == status) { - return httpResponse; - } - } - - HttpEntity responseEntity = null; - try { - responseEntity = httpResponse.getEntity(); - String message = httpClient.getMessageFromEntity(responseEntity); - throw new IOException(statusLine.getStatusCode() + ": " + message); - } finally { - EntityUtils.consumeQuietly(responseEntity); - httpResponse.close(); - } - } - - public ItemLastModified getItemLastModified(String path) throws IOException { - String url = artifactoryUrl + ITEM_LAST_MODIFIED + path + "?lastModified"; - - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(new HttpGet(url))) { - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - String message = httpClient.getMessageFromEntity(response.getEntity()); - EntityUtils.consumeQuietly(response.getEntity()); - throw new IOException("While requesting item info for path " + path + " received " + statusCode + ":" + message); - } - HttpEntity httpEntity = response.getEntity(); - if (httpEntity == null) { - throw new IOException("The path " + path + " returned empty entity"); - } - - try (InputStream content = httpEntity.getContent()) { - JsonNode result = httpClient.getJsonNode(content); - JsonNode lastModified = result.get("lastModified"); - JsonNode uri = result.get("uri"); - if (lastModified == null || uri == null) { - throw new IOException("Unexpected JSON response when requesting info for path " + path + httpClient.getMessageFromEntity(response.getEntity())); - } - return new ItemLastModified(uri.asText(), lastModified.asText()); - } - } - } - - /** - * Deploys the artifact to the destination repository. - * - * @param details Details about the deployed artifact - * @return ArtifactoryResponse The response content received from Artifactory - * @throws IOException On any connection error - */ - public ArtifactoryUploadResponse deployArtifact(DeployDetails details) throws IOException { - return deployArtifact(details, null); - } - - /** - * Deploys the artifact to the destination repository, with addition of prefix to the printed log. - * - * @param details Details about the deployed artifact - * @param logPrefix Will be printed as a log-prefix - * @return - * @throws IOException On any connection error - */ - public ArtifactoryUploadResponse deployArtifact(DeployDetails details, String logPrefix) throws IOException { - String deploymentPath = buildDeploymentPath(details); - logPrefix = logPrefix == null ? "" : logPrefix + " "; - log.info(logPrefix + "Deploying artifact: " + deploymentPath); - return doDeployArtifact(details, deploymentPath); - } - - private String buildDeploymentPath(DeployDetails details) throws IOException { - List pathComponents = new ArrayList(); - pathComponents.add(encodeUrl(artifactoryUrl)); - pathComponents.add(DeploymentUrlUtils.encodePath(details.getTargetRepository())); - pathComponents.add(DeploymentUrlUtils.encodePath(details.getArtifactPath())); - return StringUtils.join(pathComponents, "/"); - } - - private ArtifactoryUploadResponse doDeployArtifact(DeployDetails details, String deploymentPath) throws IOException { - ArtifactoryUploadResponse response = uploadFile(details, deploymentPath); - // Artifactory 2.3.2+ will take the checksum from the headers of the put request for the file - if (!getArtifactoryVersion().isAtLeast(new ArtifactoryVersion("2.3.2"))) { - uploadChecksums(details, deploymentPath); - } - return response; - } - - /** - * @return Artifactory version if working against a compatible version of Artifactory - */ - public ArtifactoryVersion verifyCompatibleArtifactoryVersion() throws VersionException { - ArtifactoryVersion version; - try { - version = httpClient.getVersion(); - } catch (IOException e) { - throw new VersionException("Error occurred while requesting version information: " + e, e, - VersionCompatibilityType.NOT_FOUND); - } - if (version.isNotFound()) { - throw new VersionException( - "There is either an incompatible or no instance of Artifactory at the provided URL.", - VersionCompatibilityType.NOT_FOUND); - } - boolean isCompatibleArtifactory = version.isAtLeast(ArtifactoryHttpClient.MINIMAL_ARTIFACTORY_VERSION); - if (!isCompatibleArtifactory) { - throw new VersionException("This plugin is compatible with version " + ArtifactoryHttpClient.MINIMAL_ARTIFACTORY_VERSION + - " of Artifactory and above. Please upgrade your Artifactory server!", - VersionCompatibilityType.INCOMPATIBLE); - } - return version; - } - - public CloseableHttpResponse stageBuild(String buildName, String buildNumber, Promotion promotion) throws IOException { - if (StringUtils.isBlank(buildName)) { - throw new IllegalArgumentException("Build name is required for promotion."); - } - if (StringUtils.isBlank(buildNumber)) { - throw new IllegalArgumentException("Build number is required for promotion."); - } - - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append(BUILD_REST_URL).append("/promote/"). - append(encodeUrl(buildName)).append("/").append(encodeUrl(buildNumber)); - - String promotionJson = toJsonString(promotion); - - HttpPost httpPost = new HttpPost(urlBuilder.toString()); - - StringEntity stringEntity = new StringEntity(promotionJson); - stringEntity.setContentType("application/vnd.org.jfrog.artifactory.build.PromotionRequest+json"); - httpPost.setEntity(stringEntity); - - log.info("Promoting build " + buildName + ", #" + buildNumber); - return httpClient.getHttpClient().execute(httpPost); - } - - public CloseableHttpResponse distributeBuild(String buildName, String buildNumber, Distribution promotion) throws IOException { - if (StringUtils.isBlank(buildName)) { - throw new IllegalArgumentException("Build name is required for distribution."); - } - if (StringUtils.isBlank(buildNumber)) { - throw new IllegalArgumentException("Build number is required for distribution."); - } - - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append(BUILD_REST_URL).append("/distribute/"). - append(encodeUrl(buildName)).append("/").append(encodeUrl(buildNumber)); - - String distributionJson = toJsonString(promotion); - - HttpPost httpPost = new HttpPost(urlBuilder.toString()); - - StringEntity stringEntity = new StringEntity(distributionJson); - stringEntity.setContentType("application/json"); - httpPost.setEntity(stringEntity); - - log.info("Distributing build " + buildName + ", #" + buildNumber); - return httpClient.getHttpClient().execute(httpPost); - } - - public Map> getUserPluginInfo() throws IOException { - HttpGet getPlugins = new HttpGet(artifactoryUrl + "/api/plugins"); - try (CloseableHttpResponse getResponse = httpClient.getHttpClient().execute(getPlugins)) { - StatusLine statusLine = getResponse.getStatusLine(); - HttpEntity responseEntity = getResponse.getEntity(); - if (statusLine.getStatusCode() != HttpStatus.SC_OK) { - String message = httpClient.getMessageFromEntity(responseEntity); - EntityUtils.consumeQuietly(responseEntity); - throw new IOException("Failed to obtain user plugin information. Status code: " + statusLine.getStatusCode() + ": " + message); - } - if (responseEntity == null) { - return new HashMap<>(); - } - - try (InputStream content = responseEntity.getContent()) { - JsonParser parser = httpClient.createJsonParser(content); - return parser.readValueAs(Map.class); - } - } - } - - public CloseableHttpResponse executeUserPlugin(String executionName, Map requestParams) throws IOException { - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append("/api/plugins/execute/") - .append(executionName).append("?"); - appendParamsToUrl(requestParams, urlBuilder); - HttpPost postRequest = new HttpPost(urlBuilder.toString()); - return httpClient.getHttpClient().execute(postRequest); - } - - public Map getStagingStrategy(String strategyName, String buildName, Map requestParams) - throws IOException { - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append("/api/plugins/build/staging/") - .append(encodeUrl(strategyName)).append("?buildName=") - .append(encodeUrl(buildName)).append("&"); - appendParamsToUrl(requestParams, urlBuilder); - HttpGet getRequest = new HttpGet(urlBuilder.toString()); - - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(getRequest)) { - StatusLine statusLine = response.getStatusLine(); - HttpEntity responseEntity = response.getEntity(); - if (statusLine.getStatusCode() != HttpStatus.SC_OK) { - String message = httpClient.getMessageFromEntity(responseEntity); - EntityUtils.consumeQuietly(responseEntity); - throw new IOException("Failed to obtain staging strategy. Status code: " + statusLine.getStatusCode() + message); - } - if (responseEntity == null) { - return new HashMap<>(); - } - try (InputStream content = responseEntity.getContent()) { - JsonParser parser = httpClient.createJsonParser(content); - return parser.readValueAs(Map.class); - } - } - } - - public CloseableHttpResponse executePromotionUserPlugin(String promotionName, String buildName, String buildNumber, - Map requestParams) throws IOException { - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append("/api/plugins/build/promote/") - .append(promotionName).append("/").append(encodeUrl(buildName)).append("/") - .append(encodeUrl(buildNumber)).append("?"); - appendParamsToUrl(requestParams, urlBuilder); - HttpPost postRequest = new HttpPost(urlBuilder.toString()); - return httpClient.getHttpClient().execute(postRequest); - } - - public CloseableHttpResponse executeUpdateFileProperty(String itemPath, String properties) throws IOException { - StringBuilder urlBuilder = new StringBuilder(artifactoryUrl).append("/api/storage/") - .append(encodeUrl(itemPath)).append("?").append("properties=").append(encodeUrl(properties)); - - HttpPut postRequest = new HttpPut(urlBuilder.toString()); - return httpClient.getHttpClient().execute(postRequest); - } - - private void appendParamsToUrl(Map requestParams, StringBuilder urlBuilder) - throws UnsupportedEncodingException { - if ((requestParams != null) && !requestParams.isEmpty()) { - urlBuilder.append("params="); - Iterator> paramEntryIterator = requestParams.entrySet().iterator(); - String encodedPipe = encodeUrl("|"); - while (paramEntryIterator.hasNext()) { - Map.Entry paramEntry = paramEntryIterator.next(); - urlBuilder.append(encodeUrl(paramEntry.getKey())); - String paramValue = paramEntry.getValue(); - if (StringUtils.isNotBlank(paramValue)) { - urlBuilder.append("=").append(encodeUrl(paramValue)); - } - - if (paramEntryIterator.hasNext()) { - - urlBuilder.append(encodedPipe); - } - } - } - } - - public String buildInfoToJsonString(Build buildInfo) throws Exception { - ArtifactoryVersion version = verifyCompatibleArtifactoryVersion(); - //From Artifactory 2.2.3 we do not need to discard new properties in order to avoid a server side exception on - //JSON parsing. Our JSON writer is configured to discard null values. - if (!version.isAtLeast(ArtifactoryHttpClient.UNKNOWN_PROPERTIES_TOLERANT_ARTIFACTORY_VERSION)) { - buildInfo.setBuildAgent(null); - buildInfo.setParentName(null); - buildInfo.setParentNumber(null); - } - //From Artifactory 2.2.4 we also handle non-numeric build numbers - if (!version.isAtLeast(ArtifactoryHttpClient.NON_NUMERIC_BUILD_NUMBERS_TOLERANT_ARTIFACTORY_VERSION)) { - String buildNumber = buildInfo.getNumber(); - verifyNonNumericBuildNumber(buildNumber); - String parentBuildNumber = buildInfo.getParentNumber(); - verifyNonNumericBuildNumber(parentBuildNumber); - } - return toJsonString(buildInfo); - } - - String toJsonString(Object object) throws IOException { - JsonFactory jsonFactory = httpClient.createJsonFactory(); - StringWriter writer = new StringWriter(); - JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(writer); - jsonGenerator.useDefaultPrettyPrinter(); - jsonGenerator.writeObject(object); - String result = writer.getBuffer().toString(); - return result; - } - - private Build getBuildFromJson(String buildInfoJson) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - JsonNode actualObj = mapper.readTree(buildInfoJson); - return mapper.readValue(actualObj.get("buildInfo").toString(), Build.class); - } - - private void verifyNonNumericBuildNumber(String buildNumber) { - if (buildNumber != null) { - try { - Long.parseLong(buildNumber); - } catch (NumberFormatException e) { - throw new IllegalArgumentException( - "Cannot handle build/parent build number: " + buildNumber + - ". Non-numeric build numbers are supported by Artifactory version " + - ArtifactoryHttpClient.NON_NUMERIC_BUILD_NUMBERS_TOLERANT_ARTIFACTORY_VERSION + - " and above. Please upgrade your Artifactory or use numeric build numbers."); - } - } - } - - private ArtifactoryUploadResponse uploadFile(DeployDetails details, String uploadUrl) throws IOException { - - ArtifactoryUploadResponse response = tryChecksumDeploy(details, uploadUrl); - if (response != null) { - // Checksum deploy was performed: - return response; - } - - HttpPut httpPut = createHttpPutMethod(details, uploadUrl); - // add the 100 continue directive - httpPut.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE); - - if (details.isExplode()) { - httpPut.addHeader("X-Explode-Archive", "true"); - } - - FileEntity fileEntity = new FileEntity(details.getFile(), "binary/octet-stream"); - - response = httpClient.upload(httpPut, fileEntity); - int statusCode = response.getStatusLine().getStatusCode(); - - //Accept both 200, and 201 for backwards-compatibility reasons - if ((statusCode != HttpStatus.SC_CREATED) && (statusCode != HttpStatus.SC_OK)) { - throw new IOException("Failed to deploy file. Status code: " + statusCode + getMessage(response)); - } - - return response; - } - - private ArtifactoryUploadResponse tryChecksumDeploy(DeployDetails details, String uploadUrl) throws UnsupportedEncodingException { - // Try checksum deploy only on file size equal or greater than 'minChecksumDeploySizeKb' - long fileLength = details.getFile().length(); - if (fileLength < minChecksumDeploySizeKb * 1024) { - log.debug("Skipping checksum deploy of file size " + fileLength + " bytes, falling back to regular deployment."); - return null; - } - - if (details.isExplode()) { - log.debug("Skipping checksum deploy due to explode file request."); - return null; - } - - // Artifactory 2.5.1+ has efficient checksum deployment (checks if the artifact already exists by it's checksum) - if (!getArtifactoryVersion().isAtLeast(new ArtifactoryVersion("2.5.1"))) { - return null; - } - - HttpPut httpPut = createHttpPutMethod(details, uploadUrl); - // activate checksum deploy - httpPut.addHeader("X-Checksum-Deploy", "true"); - - String fileAbsolutePath = details.getFile().getAbsolutePath(); - try { - ArtifactoryUploadResponse response = httpClient.execute(httpPut); - int statusCode = response.getStatusLine().getStatusCode(); - - //Accept both 200, and 201 for backwards-compatibility reasons - if ((statusCode == HttpStatus.SC_CREATED) || (statusCode == HttpStatus.SC_OK)) { - log.debug("Successfully performed checksum deploy of file " + fileAbsolutePath + " : " + details.getSha1()); - return response; - } else { - log.debug("Failed checksum deploy of checksum '" + details.getSha1() + "' with statusCode: " + statusCode); - } - } catch (IOException e) { - log.debug("Failed artifact checksum deploy of file " + fileAbsolutePath + " : " + details.getSha1()); - } - - return null; - } - - private HttpPut createHttpPutMethod(DeployDetails details, String uploadUrl) throws UnsupportedEncodingException { - StringBuilder deploymentPathBuilder = new StringBuilder().append(uploadUrl); - deploymentPathBuilder.append(DeploymentUrlUtils.buildMatrixParamsString(details.getProperties(), true)); - HttpPut httpPut = new HttpPut(deploymentPathBuilder.toString()); - httpPut.addHeader(SHA1_HEADER_NAME, details.getSha1()); - httpPut.addHeader(MD5_HEADER_NAME, details.getMd5()); - log.debug("Full Artifact Http path: " + httpPut + "\n@Http Headers: " + Arrays.toString(httpPut.getAllHeaders())); - return httpPut; - } - - public void uploadChecksums(DeployDetails details, String uploadUrl) throws IOException { - Map checksums = getChecksumMap(details); - String fileAbsolutePath = details.getFile().getAbsolutePath(); - String sha1 = checksums.get("SHA1"); - if (StringUtils.isNotBlank(sha1)) { - log.debug("Uploading SHA1 for file " + fileAbsolutePath + " : " + sha1); - String sha1Url = uploadUrl + ".sha1" + DeploymentUrlUtils.buildMatrixParamsString(details.getProperties(), true); - HttpPut putSha1 = new HttpPut(sha1Url); - StringEntity sha1StringEntity = new StringEntity(sha1); - ArtifactoryUploadResponse response = httpClient.upload(putSha1, sha1StringEntity); - StatusLine sha1StatusLine = response.getStatusLine(); - int sha1StatusCode = sha1StatusLine.getStatusCode(); - - //Accept both 200, and 201 for backwards-compatibility reasons - if ((sha1StatusCode != HttpStatus.SC_CREATED) && (sha1StatusCode != HttpStatus.SC_OK)) { - throw new IOException("Failed to deploy SHA1 checksum. Status code: " + sha1StatusCode + getMessage(response)); - } - } - String md5 = checksums.get("MD5"); - if (StringUtils.isNotBlank(md5)) { - log.debug("Uploading MD5 for file " + fileAbsolutePath + " : " + md5); - String md5Url = uploadUrl + ".md5" + DeploymentUrlUtils.buildMatrixParamsString(details.getProperties(), true); - HttpPut putMd5 = new HttpPut(md5Url); - StringEntity md5StringEntity = new StringEntity(md5); - ArtifactoryUploadResponse response = httpClient.upload(putMd5, md5StringEntity); - StatusLine md5StatusLine = response.getStatusLine(); - int md5StatusCode = md5StatusLine.getStatusCode(); - - //Accept both 200, and 201 for backwards-compatibility reasons - if ((md5StatusCode != HttpStatus.SC_CREATED) && (md5StatusCode != HttpStatus.SC_OK)) { - throw new IOException("Failed to deploy MD5 checksum. Status code: " + md5StatusCode + getMessage(response)); - } - } - } - - private Map getChecksumMap(DeployDetails details) throws IOException { - Map checksums = new HashMap<>(); - - List checksumTypeList = new ArrayList<>(); - - if (StringUtils.isBlank(details.getMd5())) { - checksumTypeList.add("MD5"); - } else { - checksums.put("MD5", details.getMd5()); - } - - if (StringUtils.isBlank(details.getSha1())) { - checksumTypeList.add("SHA1"); - } else { - checksums.put("SHA1", details.getSha1()); - } - - if (!checksumTypeList.isEmpty()) { - try { - checksums.putAll(FileChecksumCalculator.calculateChecksums(details.getFile(), - checksumTypeList.toArray(new String[checksumTypeList.size()]))); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - return checksums; - } - - private void throwHttpIOException(String message, StatusLine statusLine) throws IOException { - String errorMessage = new StringBuilder(message).append(" HTTP response code: "). - append(statusLine.getStatusCode()).append(". HTTP response message: "). - append(statusLine.getReasonPhrase()).toString(); - throw new IOException(errorMessage); - } - - /** - * Returns the response message - * - * @param response from Artifactory - * @return the response message String. - */ - private String getMessage(ArtifactoryUploadResponse response) { - String responseMessage = ""; - if (response.getErrors() != null) { - responseMessage = getResponseMessage(response.getErrors()); - if (StringUtils.isNotBlank(responseMessage)) { - responseMessage = " Response message: " + responseMessage; - } - } - return responseMessage; - } - - /** - * @param errorList errors list returned from Artifactory. - * @return response message string. - */ - private String getResponseMessage(List errorList) { - if (errorList == null || errorList.isEmpty()) { - return ""; - } - StringBuilder builder = new StringBuilder("Artifactory returned the following errors: "); - for (ArtifactoryUploadResponse.Error error : errorList) { - builder.append("\n"). - append(error.getMessage()). - append(" Status code: "). - append(error.getStatus()); - } - return builder.toString(); - } - - public void reportUsage(UsageReporter usageReporter) throws IOException { - // Check Artifactory supported version. - ArtifactoryVersion version = getArtifactoryVersion(); - if (version.isNotFound()) { - throw new IOException("Could not get Artifactory version."); - } - if (!version.isAtLeast(USAGE_ARTIFACTORY_MIN_VERSION)) { - throw new IOException("Usage report is not supported on targeted Artifactory server."); - } - - // Create request. - String url = artifactoryUrl + USAGE_API; - String encodedUrl = ArtifactoryHttpClient.encodeUrl(url); - String requestBody = new JsonSerializer().toJSON(usageReporter); - StringEntity entity = new StringEntity(requestBody, "UTF-8"); - entity.setContentType("application/json"); - HttpPost request = new HttpPost(encodedUrl); - request.setEntity(entity); - - // Send request - try (CloseableHttpResponse httpResponse = httpClient.getHttpClient().execute(request)) { - EntityUtils.consumeQuietly(httpResponse.getEntity()); - StatusLine statusLine = httpResponse.getStatusLine(); - if (statusLine.getStatusCode() != HttpStatus.SC_OK && statusLine.getStatusCode() != HttpStatus.SC_ACCEPTED) { - throw new IOException(String.format("Artifactory response: %s %s", statusLine.getStatusCode(), statusLine.getReasonPhrase())); - } - } - } - - public void sendBuildRetention(BuildRetention buildRetention, String buildName, boolean async) throws IOException { - String buildRetentionJson = toJsonString(buildRetention); - String url = artifactoryUrl + BUILD_RETENTION_REST_URL + buildName + BUILD_RETENTION_REST_ASYNC_PARAM + async; - HttpPost httpPost = new HttpPost(url); - try { - log.info(createBuildRetentionLogMsg(buildRetention, async)); - log.debug(buildRetentionJson); - sendHttpEntityRequest(httpPost, buildRetentionJson, APPLICATION_JSON); - } catch (IOException e) { - throw new IOException("Failed to execute build retention", e); - } - } - - /** - * Sends build info to Artifactory. - * - * @param buildInfo The build info to send - * @throws IOException On any connection error - */ - public void sendBuildInfo(Build buildInfo, String platformUrl) throws IOException { - log.debug("Sending build info: " + buildInfo); - try { - sendBuildInfo(buildInfoToJsonString(buildInfo), buildInfo.getProject()); - } catch (Exception e) { - throw new IOException("Could not publish build-info", e); - } - String url; - if (StringUtils.isNotBlank(platformUrl)) { - url = createBuildInfoUrl(platformUrl, buildInfo.getName(), buildInfo.getNumber(), String.valueOf(buildInfo.getStartedMillis()), buildInfo.getProject()); - } else { - url = createBuildInfoUrl(artifactoryUrl, buildInfo.getName(), buildInfo.getNumber()); - } - log.info("Build successfully deployed. Browse it in Artifactory under " + url); - } -} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryDependenciesClient.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryDependenciesClient.java deleted file mode 100644 index e6274a708..000000000 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryDependenciesClient.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2010 JFrog Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jfrog.build.extractor.clientConfiguration.client; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.*; -import org.apache.http.entity.StringEntity; -import org.apache.http.util.EntityUtils; -import org.jfrog.build.api.dependency.BuildPatternArtifacts; -import org.jfrog.build.api.dependency.BuildPatternArtifactsRequest; -import org.jfrog.build.api.dependency.PatternResultFileSet; -import org.jfrog.build.api.dependency.PropertySearchResult; -import org.jfrog.build.api.repository.RepositoryConfig; -import org.jfrog.build.api.search.AqlSearchResult; -import org.jfrog.build.api.util.Log; -import org.jfrog.build.client.ArtifactoryHttpClient; -import org.jfrog.build.client.PreemptiveHttpClient; -import org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils; -import org.jfrog.build.extractor.clientConfiguration.util.JsonSerializer; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; - -/** - * Artifactory client to perform artifacts and build dependencies related tasks. - * - * @author Noam Y. Tenne - */ -public class ArtifactoryDependenciesClient extends ArtifactoryBaseClient { - private static final String LATEST = "LATEST"; - private static final String LAST_RELEASE = "LAST_RELEASE"; - - public ArtifactoryDependenciesClient(String artifactoryUrl, String username, String password, String accessToken, Log logger) { - super(artifactoryUrl, username, password, accessToken, logger); - } - - public ArtifactoryDependenciesClient(String artifactoryUrl, String username, String password, Log logger) { - this(artifactoryUrl, username, password, StringUtils.EMPTY, logger); - } - - public ArtifactoryDependenciesClient(String artifactoryUrl, ArtifactoryHttpClient httpClient, Log logger) { - super(artifactoryUrl, httpClient, logger); - } - - /** - * Retrieves list of {@link org.jfrog.build.api.dependency.BuildPatternArtifacts} for build dependencies specified. - * - * @param requests build dependencies to retrieve outputs for. - * @return build outputs for dependencies specified. - */ - public List retrievePatternArtifacts(List requests) - throws IOException { - final String json = new JsonSerializer>().toJSON(requests); - final HttpPost post = new HttpPost(artifactoryUrl + "/api/build/patternArtifacts"); - StringEntity stringEntity = new StringEntity(json); - stringEntity.setContentType("application/vnd.org.jfrog.artifactory+json"); - post.setEntity(stringEntity); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(post); - InputStream responseStream = getResponseStream(response, "Failed to retrieve build artifacts report")) { - return readJsonResponse(responseStream, new TypeReference>() { - }, false); - } - - } - - public PatternResultFileSet searchArtifactsByPattern(String pattern) throws IOException { - String url = artifactoryUrl + "/api/search/pattern?pattern=" + pattern; - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(new HttpGet(url)); - InputStream responseStream = getResponseStream(response, "Failed to search artifact by the pattern '" + pattern + "'")) { - return readJsonResponse(responseStream, new TypeReference() { - }, false); - } - } - - public PropertySearchResult searchArtifactsByProperties(String properties) throws IOException { - String replacedProperties = StringUtils.replaceEach(properties, new String[]{";", "+"}, new String[]{"&", ""}); - String url = artifactoryUrl + "/api/search/prop?" + replacedProperties; - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(new HttpGet(url)); - InputStream responseStream = getResponseStream(response, "Failed to search artifact by the properties '" + properties + "'")) { - return readJsonResponse(responseStream, new TypeReference() { - }, false); - } - } - - public AqlSearchResult searchArtifactsByAql(String aql) throws IOException { - String url = artifactoryUrl + "/api/search/aql"; - HttpPost httpPost = new HttpPost(url); - StringEntity entity = new StringEntity(aql); - httpPost.setEntity(entity); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(httpPost); - InputStream responseStream = getResponseStream(response, "Failed to search artifact by the aql '" + aql + "'")) { - return readJsonResponse(responseStream, new TypeReference() { - }, true); - } - } - - public Properties getNpmAuth() throws IOException { - String url = artifactoryUrl + "/api/npm/auth"; - HttpGet httpGet = new HttpGet(url); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(httpGet); - InputStream responseStream = getResponseStream(response, "npm Auth request failed")) { - Properties properties = new Properties(); - properties.load(responseStream); - return properties; - } - } - - private InputStream getResponseStream(HttpResponse response, String errorMessage) throws IOException { - if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { - HttpEntity entity = response.getEntity(); - if (entity == null) { - return null; - } - return entity.getContent(); - } - throw new IOException(errorMessage + ": " + response.getStatusLine()); - } - - /** - * Reads HTTP response and converts it to object of the type specified. - * - * @param responseStream response to read - * @param valueType response object type - * @param response object type - * @return response object converted from HTTP Json reponse to the type specified. - * @throws java.io.IOException if reading or converting response fails. - */ - private T readJsonResponse(InputStream responseStream, TypeReference valueType, boolean ignoreMissingFields) - throws IOException { - JsonParser parser = httpClient.createJsonParser(responseStream); - if (ignoreMissingFields) { - ((ObjectMapper) parser.getCodec()).configure(FAIL_ON_UNKNOWN_PROPERTIES, false); - } - return parser.readValueAs(valueType); - } - - public CloseableHttpResponse downloadArtifact(String downloadUrl) throws IOException { - return executeDownload(downloadUrl, false, null); - } - - public CloseableHttpResponse downloadArtifact(String downloadUrl, Map headers) throws IOException { - return executeDownload(downloadUrl, false, headers); - } - - public CloseableHttpResponse getArtifactMetadata(String artifactUrl) throws IOException { - return executeDownload(artifactUrl, true, null); - } - - public boolean isArtifactoryOSS() throws IOException { - return !httpClient.getVersion().hasAddons(); - } - - public boolean isLocalRepo(String repo) throws IOException { - return "local".equals(getRepoType(repo)); - } - - public boolean isRemoteRepo(String repo) throws IOException { - return "remote".equals(getRepoType(repo)); - } - - private String getRepoType(String repo) throws IOException { - String url = artifactoryUrl + "/api/repositories/" + repo; - HttpGet httpGet = new HttpGet(url); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(httpGet); - InputStream responseStream = getResponseStream(response, "Failed to retrieve repository configuration '" + repo + "'")) { - RepositoryConfig repoDetails = readJsonResponse(responseStream, new TypeReference() { - }, true); - return repoDetails.getRclass(); - } - } - - private CloseableHttpResponse executeDownload(String artifactUrl, boolean isHead, Map headers) throws IOException { - PreemptiveHttpClient client = httpClient.getHttpClient(); - - artifactUrl = ArtifactoryHttpClient.encodeUrl(artifactUrl); - HttpRequestBase httpRequest = isHead ? new HttpHead(artifactUrl) : new HttpGet(artifactUrl); - - // Explicitly force keep alive - httpRequest.setHeader("Connection", "Keep-Alive"); - // Add all required headers to the request - if (headers != null) { - for (Map.Entry entry : headers.entrySet()) { - httpRequest.setHeader(entry.getKey(), entry.getValue()); - } - } - - CloseableHttpResponse response = client.execute(httpRequest); - StatusLine statusLine = response.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - if (statusCode == HttpStatus.SC_NOT_FOUND) { - throw new FileNotFoundException("Unable to find " + artifactUrl); - } - - if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_PARTIAL_CONTENT) { - EntityUtils.consumeQuietly(response.getEntity()); - throw new IOException("Error downloading " + artifactUrl + ". Code: " + statusCode + " Message: " + - statusLine.getReasonPhrase()); - } - return response; - } - - public void setProperties(String urlPath, String props) throws IOException { - String url = ArtifactoryHttpClient.encodeUrl(urlPath + "?properties="); - url += DeploymentUrlUtils.buildMatrixParamsString(mapPropsString(props), true); - HttpPut httpPut = new HttpPut(url); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(httpPut)) { - checkNoContent(response, "Failed to set properties to '" + urlPath + "'"); - } - } - - private ArrayListMultimap mapPropsString(String props) { - ArrayListMultimap propsMap = ArrayListMultimap.create(); - String[] propsList = props.split(";"); - for (String prop : propsList) { - String[] propParts = prop.split("="); - propsMap.put(propParts[0], propParts[1]); - } - return propsMap; - } - - public void deleteProperties(String urlPath, String props) throws IOException { - String url = ArtifactoryHttpClient.encodeUrl(urlPath + "?properties=" + props); - HttpDelete httpDelete = new HttpDelete(url); - try (CloseableHttpResponse response = httpClient.getHttpClient().execute(httpDelete)) { - checkNoContent(response, "Failed to delete properties to '" + urlPath + "'"); - } - } - - private void checkNoContent(HttpResponse response, String errorMessage) throws IOException { - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_NO_CONTENT) { - throw new IOException(errorMessage + ": " + response.getStatusLine()); - } - } - - /** - * Retrieves build number for the provided build name. For LATEST / LAST_RELEASE build numbers, retrieves actual build number from Artifactory. - * - * @return actual build number, null if buildName is not found. - */ - public String getLatestBuildNumberFromArtifactory(String buildName, String buildNumber, String project) throws IOException { - if (LATEST.equals(buildNumber.trim()) || LAST_RELEASE.equals(buildNumber.trim())) { - if (isArtifactoryOSS()) { - throw new IllegalArgumentException(String.format("%s is not supported in Artifactory OSS.", buildNumber)); - } - List artifactsRequest = Lists.newArrayList(); - artifactsRequest.add(new BuildPatternArtifactsRequest(buildName, buildNumber, project)); - List artifactsResponses = retrievePatternArtifacts(artifactsRequest); - // Artifactory returns null if no build was found - if (artifactsResponses.get(0) != null) { - buildNumber = artifactsResponses.get(0).getBuildNumber(); - } else { - return null; - } - } - return buildNumber; - } -} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogService.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogService.java new file mode 100644 index 000000000..ccde868d5 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogService.java @@ -0,0 +1,175 @@ +package org.jfrog.build.extractor.clientConfiguration.client; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.util.EntityUtils; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.util.URI; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static org.apache.commons.codec.binary.StringUtils.getBytesUtf8; +import static org.apache.commons.codec.binary.StringUtils.newStringUsAscii; + +/** + * JFrogService represents a generic way of processing a REST endpoint process that structures how REST sends, handles errors, and parses the response. + * + * @param - The expected result class from the JFrog REST endpoint. + */ +public abstract class JFrogService { + protected final Log log; + protected TResult result; + protected int statusCode; + protected JFrogServiceResponseType responseType; + private Header[] headers; + private ObjectMapper mapper; + + protected JFrogService(Log log) { + this.log = log; + responseType = JFrogServiceResponseType.OBJECT; + } + + protected JFrogService(Log log, JFrogServiceResponseType responseType) { + this.log = log; + this.responseType = responseType; + } + + protected static void throwException(HttpEntity entity, int statusCode) throws IOException { + if (entity == null) { + throw new IllegalArgumentException("JFrog service failed. Received " + statusCode); + } + try (InputStream stream = entity.getContent()) { + String ResponseMessage = IOUtils.toString(stream, StandardCharsets.UTF_8); + throw new IOException("JFrog service failed. Received " + statusCode + ": " + ResponseMessage); + } + } + + public static String encodeUrl(String unescaped) { + byte[] rawData = URLCodec.encodeUrl(URI.allowed_query, getBytesUtf8(unescaped)); + return newStringUsAscii(rawData); + } + + /** + * Default ObjectMapper to parse or deserialize JSON content into a Java object. + */ + protected ObjectMapper getMapper(boolean ignoreMissingFields) { + if (mapper == null) { + mapper = new ObjectMapper(); + if (ignoreMissingFields) { + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + } + mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector()); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + return mapper; + } + + public TResult getResult() { + return result; + } + + public void setResult(TResult result) { + this.result = result; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public abstract HttpRequestBase createRequest() throws IOException; + + /** + * Override this in order to parse the service response body (only for services that expect to have body in the response). + * + * @param stream - Inout stream of the response body. + */ + protected abstract void setResponse(InputStream stream) throws IOException; + + /** + * Default error handling (E.G. 404 bad request). + * + * @param entity - The returned failure response. + */ + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + if (entity == null) { + throw new IllegalArgumentException("Entity cannot be null"); + } + throwException(entity, getStatusCode()); + } + + /** + * Default execution of a service: + * 1. Send the http request + * 2. check HTTP status code. if there are any errors, throw. + * 3. Return the response result (if any is expected). + * + * @param client - http client for sending the request. + * @return - The response body object. + */ + public TResult execute(JFrogHttpClient client) throws IOException { + ensureRequirements(client); + try (CloseableHttpResponse response = client.sendRequest(createRequest())) { + if (response == null) { + return null; + } + HttpEntity entity = response.getEntity(); + try { + setStatusCode(response.getStatusLine().getStatusCode()); + setHeaders(response.getAllHeaders()); + if (getStatusCode() >= 400) { + handleUnsuccessfulResponse(entity); + } else { + processResponse(entity); + } + return getResult(); + } finally { + if (entity != null) { + EntityUtils.consumeQuietly(entity); + } + } + } + } + + private void processResponse(HttpEntity entity) throws IOException { + if (entity == null) { + handleEmptyEntity(); + return; + } + try (InputStream stream = entity.getContent()) { + long contentLength = entity.getContentLength(); + if (contentLength == 0 || responseType == JFrogServiceResponseType.EMPTY) { + return; + } + setResponse(stream); + } + } + + protected void handleEmptyEntity() throws IOException { + } + + protected void ensureRequirements(JFrogHttpClient client) throws IOException { + } + + public Header[] getHeaders() { + return headers; + } + + public void setHeaders(Header[] headers) { + this.headers = headers; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogServiceResponseType.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogServiceResponseType.java new file mode 100644 index 000000000..251b049f5 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/JFrogServiceResponseType.java @@ -0,0 +1,11 @@ +package org.jfrog.build.extractor.clientConfiguration.client; + +/** + * Client response may contain a body, this enum indicates whenever a JFrog service expects a body or not. + * EMPTY - An empty body is expected. + * OBJECT - An object inside the body is expected. + */ +public enum JFrogServiceResponseType { + EMPTY, + OBJECT +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ManagerBase.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ManagerBase.java new file mode 100644 index 000000000..13befc12f --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ManagerBase.java @@ -0,0 +1,103 @@ +package org.jfrog.build.extractor.clientConfiguration.client; + +import org.apache.commons.lang.StringUtils; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.client.ProxyConfiguration; + +import javax.net.ssl.SSLContext; + +public abstract class ManagerBase implements AutoCloseable { + protected final JFrogHttpClient jfrogHttpClient; + protected final Log log; + + protected ManagerBase(String url, String username, String password, String accessToken, Log logger) { + if (StringUtils.isNotEmpty(accessToken)) { + jfrogHttpClient = new JFrogHttpClient(url, accessToken, logger); + } else { + jfrogHttpClient = new JFrogHttpClient(url, username, password, logger); + } + log = logger; + } + + /** + * Network timeout in seconds to use both for connection establishment and for unanswered requests. + * + * @param connectionTimeout Timeout in seconds. + */ + public void setConnectionTimeout(int connectionTimeout) { + jfrogHttpClient.setConnectionTimeout(connectionTimeout); + } + + /** + * Connection Retries to perform + * + * @param connectionRetries The number of max retries. + */ + public void setConnectionRetries(int connectionRetries) { + jfrogHttpClient.setConnectionRetries(connectionRetries); + } + + /** + * Sets the proxy host and port. + * + * @param host Proxy host + * @param port Proxy port + */ + public void setProxyConfiguration(String host, int port) { + jfrogHttpClient.setProxyConfiguration(host, port, null, null); + } + + /** + * Sets the proxy details. + * + * @param host Proxy host + * @param port Proxy port + * @param username Username to authenticate with the proxy + * @param password Password to authenticate with the proxy + */ + public void setProxyConfiguration(String host, int port, String username, String password) { + jfrogHttpClient.setProxyConfiguration(host, port, username, password); + } + + public ProxyConfiguration getProxyConfiguration() { + return jfrogHttpClient.getProxyConfiguration(); + } + + /** + * Sets full proxy details. + * + * @param proxy Proxy instance {@link org.jfrog.build.client.ProxyConfiguration} + */ + public void setProxyConfiguration(ProxyConfiguration proxy) { + jfrogHttpClient.setProxyConfiguration(proxy.host, proxy.port, proxy.username, proxy.password); + } + + /** + * Log setter for the PreemptiveHttpClient for jobs like the Jenkins Generic job that uses NullLog by default. + * + * @param log Log instance + */ + public void setLog(Log log) { + jfrogHttpClient.getHttpClient().setLog(log); + } + + public void setInsecureTls(boolean insecureTls) { + jfrogHttpClient.setInsecureTls(insecureTls); + } + + public void setSslContext(SSLContext sslContext) { + jfrogHttpClient.setSslContext(sslContext); + } + + public String getUrl() { + return jfrogHttpClient.getUrl(); + } + + @Override + public void close() { + if (jfrogHttpClient != null) { + jfrogHttpClient.close(); + } + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/RepositoryType.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/RepositoryType.java new file mode 100644 index 000000000..098ba5d73 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/RepositoryType.java @@ -0,0 +1,7 @@ +package org.jfrog.build.extractor.clientConfiguration.client; + +public enum RepositoryType { + LOCAL, + REMOTE, + VIRTUAL +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/VoidJFrogService.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/VoidJFrogService.java new file mode 100644 index 000000000..23715f141 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/VoidJFrogService.java @@ -0,0 +1,17 @@ +package org.jfrog.build.extractor.clientConfiguration.client; + +import org.jfrog.build.api.util.Log; + +import java.io.IOException; +import java.io.InputStream; + +public abstract class VoidJFrogService extends JFrogService { + public VoidJFrogService(Log logger) { + super(logger, JFrogServiceResponseType.EMPTY); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + throw new UnsupportedOperationException("The service '" + getClass().getSimpleName() + "' must override the setResponse method"); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/ArtifactoryManager.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/ArtifactoryManager.java new file mode 100644 index 000000000..35e97b130 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/ArtifactoryManager.java @@ -0,0 +1,282 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.apache.http.Header; +import org.jfrog.build.api.Build; +import org.jfrog.build.api.BuildRetention; +import org.jfrog.build.api.dependency.BuildPatternArtifacts; +import org.jfrog.build.api.dependency.BuildPatternArtifactsRequest; +import org.jfrog.build.api.dependency.PatternResultFileSet; +import org.jfrog.build.api.dependency.PropertySearchResult; +import org.jfrog.build.api.release.Distribution; +import org.jfrog.build.api.release.Promotion; +import org.jfrog.build.api.search.AqlSearchResult; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.ArtifactoryUploadResponse; +import org.jfrog.build.client.ArtifactoryVersion; +import org.jfrog.build.client.ItemLastModified; +import org.jfrog.build.client.artifactoryXrayResponse.ArtifactoryXrayResponse; +import org.jfrog.build.extractor.clientConfiguration.client.ManagerBase; +import org.jfrog.build.extractor.clientConfiguration.client.RepositoryType; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.*; +import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; +import org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils; +import org.jfrog.build.extractor.usageReport.UsageReporter; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.ScanBuild.XRAY_SCAN_CONNECTION_TIMEOUT_SECS; + +public class ArtifactoryManager extends ManagerBase { + public static final String LATEST = "LATEST"; + public static final String LAST_RELEASE = "LAST_RELEASE"; + + public ArtifactoryManager(String artifactoryUrl, String username, String password, String accessToken, Log log) { + super(artifactoryUrl, username, password, accessToken, log); + } + + public ArtifactoryManager(String artifactoryUrl, String username, String password, Log log) { + super(artifactoryUrl, username, password, StringUtils.EMPTY, log); + } + + public ArtifactoryManager(String artifactoryUrl, String accessToken, Log log) { + super(artifactoryUrl, StringUtils.EMPTY, StringUtils.EMPTY, accessToken, log); + } + + public ArtifactoryManager(String artifactoryUrl, Log log) { + super(artifactoryUrl, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, log); + } + + public boolean isLocalRepo(String repositoryKey) throws IOException { + CheckRepositoryType checkRepositoryTypeService = new CheckRepositoryType(RepositoryType.LOCAL, repositoryKey, log); + return checkRepositoryTypeService.execute(jfrogHttpClient); + } + + public boolean isRemoteRepo(String repositoryKey) throws IOException { + CheckRepositoryType checkRepositoryTypeService = new CheckRepositoryType(RepositoryType.REMOTE, repositoryKey, log); + return checkRepositoryTypeService.execute(jfrogHttpClient); + } + + public void deleteProperties(String relativePath, String properties) throws IOException { + DeleteProperties deletePropertiesService = new DeleteProperties(relativePath, properties, log); + deletePropertiesService.execute(jfrogHttpClient); + } + + public void setProperties(String relativePath, String properties, boolean encodeProperties) throws IOException { + SetProperties setPropertiesService = new SetProperties(relativePath, properties, encodeProperties, log); + setPropertiesService.execute(jfrogHttpClient); + } + + public void setProperties(String relativePath, ArrayListMultimap properties, boolean encodeProperties) throws IOException { + SetProperties setPropertiesService = new SetProperties(relativePath, DeploymentUrlUtils.buildMatrixParamsString(properties, false), encodeProperties, log); + setPropertiesService.execute(jfrogHttpClient); + } + + public void distributeBuild(String buildName, String buildNumber, Distribution promotion) throws IOException { + DistributeBuild distributeBuildService = new DistributeBuild(buildName, buildNumber, promotion, log); + distributeBuildService.execute(jfrogHttpClient); + } + + public String download(String downloadFrom) throws IOException { + return download(downloadFrom, null); + } + + public String download(String downloadFrom, Map headers) throws IOException { + Download downloadService = new Download(downloadFrom, headers, log); + return downloadService.execute(jfrogHttpClient); + } + + public Header[] downloadHeaders(String downloadFrom) throws IOException { + return downloadHeaders(downloadFrom, null); + } + + public Header[] downloadHeaders(String downloadFrom, Map headers) throws IOException { + DownloadHeaders downloadHeadersService = new DownloadHeaders(downloadFrom, headers, log); + return downloadHeadersService.execute(jfrogHttpClient); + } + + public File downloadToFile(String downloadFrom, String downloadTo) throws IOException { + return downloadToFile(downloadFrom, downloadTo, null); + } + + public File downloadToFile(String downloadFrom, String downloadTo, Map headers) throws IOException { + DownloadToFile downloadToFileService = new DownloadToFile(downloadFrom, downloadTo, headers, log); + return downloadToFileService.execute(jfrogHttpClient); + } + + public void executeUserPlugin(String executionName, Map requestParams) throws IOException { + ExecuteUserPlugin executeUserPluginService = new ExecuteUserPlugin(executionName, requestParams, log); + executeUserPluginService.execute(jfrogHttpClient); + } + + public void promotionUserPlugin(String promotionName, String buildName, String buildNumber, Map requestParams) throws IOException { + PromotionUserPlugin promotionUserPlugin = new PromotionUserPlugin(promotionName, buildName, buildNumber, requestParams, log); + promotionUserPlugin.execute(jfrogHttpClient); + } + + public ItemLastModified getItemLastModified(String path) throws IOException { + GetItemLastModified getItemLastModifiedService = new GetItemLastModified(path, log); + return getItemLastModifiedService.execute(jfrogHttpClient); + } + + public Properties getNpmAuth() throws IOException { + GetNpmAuth getNpmAuthService = new GetNpmAuth(log); + return getNpmAuthService.execute(jfrogHttpClient); + } + + public ArtifactoryVersion getVersion() throws IOException { + Version versionService = new Version(log); + return versionService.execute(jfrogHttpClient); + } + + public void publishBuildInfo(Build buildInfo, String platformUrl) throws IOException { + PublishBuildInfo publishBuildInfoService = new PublishBuildInfo(buildInfo, platformUrl, log); + publishBuildInfoService.execute(jfrogHttpClient); + } + + public void sendModuleInfo(Build build) throws IOException { + SendModuleInfo sendModuleInfoService = new SendModuleInfo(build, log); + sendModuleInfoService.execute(jfrogHttpClient); + } + + public Build getBuildInfo(String buildName, String buildNumber, String project) throws IOException { + if (LATEST.equals(buildNumber.trim()) || LAST_RELEASE.equals(buildNumber.trim())) { + buildNumber = getLatestBuildNumber(buildName, buildNumber, project); + if (buildNumber == null) { + return null; + } + } + GetBuildInfo getBuildInfoService = new GetBuildInfo(buildName, buildNumber, project, log); + return getBuildInfoService.execute(jfrogHttpClient); + } + + + public List getLocalRepositoriesKeys() throws IOException { + GetRepositoriesKeys getLocalRepositoriesKeysService = new GetRepositoriesKeys(RepositoryType.LOCAL, log); + return getLocalRepositoriesKeysService.execute(jfrogHttpClient); + } + + public List getRemoteRepositoriesKeys() throws IOException { + GetRepositoriesKeys getRemoteRepositoriesKeysService = new GetRepositoriesKeys(RepositoryType.REMOTE, log); + return getRemoteRepositoriesKeysService.execute(jfrogHttpClient); + } + + public List getVirtualRepositoriesKeys() throws IOException { + GetRepositoriesKeys getVirtualRepositoriesKeysService = new GetRepositoriesKeys(RepositoryType.VIRTUAL, log); + return getVirtualRepositoriesKeysService.execute(jfrogHttpClient); + } + + public Map getStagingStrategy(String strategyName, String buildName, Map requestParams) throws IOException { + GetStagingStrategy getStagingStrategyService = new GetStagingStrategy(strategyName, buildName, requestParams, log); + return getStagingStrategyService.execute(jfrogHttpClient); + } + + public Map> getUserPluginInfo() throws IOException { + GetUserPluginInfo getUserPluginInfoService = new GetUserPluginInfo(log); + return getUserPluginInfoService.execute(jfrogHttpClient); + } + + public boolean isRepositoryExist(String repositoryKey) throws IOException { + IsRepositoryExist IsRepositoryExistService = new IsRepositoryExist(repositoryKey, log); + return IsRepositoryExistService.execute(jfrogHttpClient); + } + + public void reportUsage(UsageReporter usageReporter) throws IOException { + ReportUsage reportUsageService = new ReportUsage(usageReporter, log); + reportUsageService.execute(jfrogHttpClient); + } + + public List retrievePatternArtifacts(List requests) throws IOException { + RetrievePatternArtifacts retrievePatternArtifactsService = new RetrievePatternArtifacts(requests, log); + return retrievePatternArtifactsService.execute(jfrogHttpClient); + } + + public ArtifactoryXrayResponse scanBuild(String buildName, String buildNumber, String context) throws IOException { + setConnectionTimeout(XRAY_SCAN_CONNECTION_TIMEOUT_SECS); + ScanBuild scanBuildService = new ScanBuild(buildName, buildNumber, context, log); + return scanBuildService.execute(jfrogHttpClient); + } + + public AqlSearchResult searchArtifactsByAql(String aql) throws IOException { + SearchArtifactsByAql searchArtifactsByAqlService = new SearchArtifactsByAql(aql, log); + return searchArtifactsByAqlService.execute(jfrogHttpClient); + } + + public PatternResultFileSet searchArtifactsByPattern(String pattern) throws IOException { + SearchArtifactsByPattern searchArtifactsByPatternService = new SearchArtifactsByPattern(pattern, log); + return searchArtifactsByPatternService.execute(jfrogHttpClient); + } + + public PropertySearchResult searchArtifactsByProperties(String properties) throws IOException { + SearchArtifactsByProperties searchArtifactsByPropertiesService = new SearchArtifactsByProperties(properties, log); + return searchArtifactsByPropertiesService.execute(jfrogHttpClient); + } + + public void sendBuildRetention(BuildRetention buildRetention, String buildName, String project, boolean async) throws IOException { + SendBuildRetention sendBuildRetentionService = new SendBuildRetention(buildRetention, buildName, project, async, log); + sendBuildRetentionService.execute(jfrogHttpClient); + } + + public void stageBuild(String buildName, String buildNumber, Promotion promotion) throws IOException { + StageBuild stageBuildService = new StageBuild(buildName, buildNumber, promotion, log); + stageBuildService.execute(jfrogHttpClient); + } + + public void updateFileProperty(String itemPath, String properties) throws IOException { + UpdateFileProperty updateFilePropertyService = new UpdateFileProperty(itemPath, properties, log); + updateFilePropertyService.execute(jfrogHttpClient); + } + + public ArtifactoryUploadResponse upload(DeployDetails details) throws IOException { + return upload(details, null, null); + } + + public ArtifactoryUploadResponse upload(DeployDetails details, String logPrefix) throws IOException { + return upload(details, logPrefix, null); + } + + public ArtifactoryUploadResponse upload(DeployDetails details, String logPrefix, Integer MinChecksumDeploySizeKb) throws IOException { + Upload uploadService = new Upload(details, logPrefix, MinChecksumDeploySizeKb, log); + return uploadService.execute(jfrogHttpClient); + } + + public void deleteRepository(String repository) throws IOException { + DeleteRepository deleteRepositoryService = new DeleteRepository(repository, log); + deleteRepositoryService.execute(jfrogHttpClient); + } + + public void deleteRepositoryContent(String repository) throws IOException { + DeleteRepositoryContent deleteRepositoryContentService = new DeleteRepositoryContent(repository, log); + deleteRepositoryContentService.execute(jfrogHttpClient); + } + + public void createRepository(String repository, String repositoryJsonConfig) throws IOException { + CreateRepository createRepository = new CreateRepository(repository, repositoryJsonConfig, log); + createRepository.execute(jfrogHttpClient); + } + + public String getLatestBuildNumber(String buildName, String latestType, String project) throws IOException { + if (!LATEST.equals(latestType.trim()) && LAST_RELEASE.equals(latestType.trim())) { + log.warn("GetLatestBuildNumber accepts only two latest types: LATEST or LAST_RELEASE"); + return null; + } + Version versionService = new Version(log); + if (versionService.execute(jfrogHttpClient).isOSS()) { + throw new IllegalArgumentException(String.format("%s is not supported in Artifactory OSS.", latestType)); + } + List artifactsRequest = Lists.newArrayList(); + artifactsRequest.add(new BuildPatternArtifactsRequest(buildName, latestType, project)); + List artifactsResponses = retrievePatternArtifacts(artifactsRequest); + // Artifactory returns null if no build was found + if (artifactsResponses.get(0) != null) { + return artifactsResponses.get(0).getBuildNumber(); + } + return null; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CheckRepositoryType.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CheckRepositoryType.java new file mode 100644 index 000000000..5afb2ace9 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CheckRepositoryType.java @@ -0,0 +1,47 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.repository.RepositoryConfig; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; +import org.jfrog.build.extractor.clientConfiguration.client.RepositoryType; + +import java.io.IOException; +import java.io.InputStream; + +public class CheckRepositoryType extends JFrogService { + private static final String REPOS_REST_URL = "api/repositories/"; + private final RepositoryType repositoryType; + private final String repositoryKey; + + public CheckRepositoryType(RepositoryType repositoryType, String repositoryKey, Log log) { + super(log); + this.repositoryType = repositoryType; + this.repositoryKey = repositoryKey; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpGet(REPOS_REST_URL + repositoryKey); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + RepositoryConfig repositoryConfig = getMapper(true).readValue(stream, RepositoryConfig.class); + switch (repositoryType) { + case LOCAL: + result = "local".equals(repositoryConfig.getRclass()); + break; + case REMOTE: + result = "remote".equals(repositoryConfig.getRclass()); + } + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to retrieve repository configuration '" + repositoryKey + "'"); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CreateRepository.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CreateRepository.java new file mode 100644 index 000000000..34031a4c5 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/CreateRepository.java @@ -0,0 +1,30 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +public class CreateRepository extends VoidJFrogService { + private static final String CREATE_REPOSITORY_ENDPOINT = "api/repositories/"; + private final String repositoryKey; + private final String repositoryJsonConfig; + + public CreateRepository(String repositoryKey, String repositoryJsonConfig, Log logger) { + super(logger); + this.repositoryKey = repositoryKey; + this.repositoryJsonConfig = repositoryJsonConfig; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + HttpPut request = new HttpPut(CREATE_REPOSITORY_ENDPOINT + repositoryKey); + StringEntity stringEntity = new StringEntity(repositoryJsonConfig, ContentType.create("application/json")); + request.setEntity(stringEntity); + return request; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteProperties.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteProperties.java new file mode 100644 index 000000000..4df56395e --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteProperties.java @@ -0,0 +1,34 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +public class DeleteProperties extends VoidJFrogService { + public static final String DELETE_PROPERTIES_ENDPOINT = "api/storage/"; + + private final String relativePath; + private final String properties; + + public DeleteProperties(String relativePath, String properties, Log log) { + super(log); + this.relativePath = relativePath; + this.properties = properties; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String requestUrl = DELETE_PROPERTIES_ENDPOINT + encodeUrl(relativePath + "?properties=" + properties); + return new HttpDelete(requestUrl); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to delete properties to '" + relativePath + "'"); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepository.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepository.java new file mode 100644 index 000000000..94088e07b --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepository.java @@ -0,0 +1,23 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +public class DeleteRepository extends VoidJFrogService { + private static final String API_REPOSITORIES = "api/repositories/"; + private final String repository; + + public DeleteRepository(String repository, Log logger) { + super(logger); + this.repository = repository; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpDelete(API_REPOSITORIES + encodeUrl(repository)); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepositoryContent.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepositoryContent.java new file mode 100644 index 000000000..d27751666 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DeleteRepositoryContent.java @@ -0,0 +1,33 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.FileNotFoundException; +import java.io.IOException; + +public class DeleteRepositoryContent extends VoidJFrogService { + private final String repository; + + public DeleteRepositoryContent(String repository, Log logger) { + super(logger); + this.repository = repository; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpDelete(encodeUrl(repository)); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + if (statusCode == HttpStatus.SC_UNAUTHORIZED) { + throw new FileNotFoundException("Bad credentials"); + } + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DistributeBuild.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DistributeBuild.java new file mode 100644 index 000000000..097058687 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DistributeBuild.java @@ -0,0 +1,64 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.release.Distribution; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; +import java.io.InputStream; + +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + +public class DistributeBuild extends VoidJFrogService { + private static final String BUILD_REST_URL = "api/build"; + private final String buildName; + private final String buildNumber; + private final Distribution promotion; + + public DistributeBuild(String buildName, String buildNumber, Distribution promotion, Log log) { + super(log); + this.buildName = buildName; + this.buildNumber = buildNumber; + this.promotion = promotion; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String urlBuilder = BUILD_REST_URL + "/distribute/" + + encodeUrl(buildName) + "/" + encodeUrl(buildNumber); + HttpPost request = new HttpPost(urlBuilder); + StringEntity stringEntity = new StringEntity(toJsonString(promotion)); + stringEntity.setContentType("application/json"); + request.setEntity(stringEntity); + log.info("Distributing build " + buildName + ", #" + buildNumber); + return request; + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + log.info(String.format("Successfully distributed build %s/%s", buildName, buildNumber)); + + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) { + if (StringUtils.isBlank(buildName)) { + throw new IllegalArgumentException("Build name is required for distribution."); + } + if (StringUtils.isBlank(buildNumber)) { + throw new IllegalArgumentException("Build number is required for distribution."); + } + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Distribution failed."); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Download.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Download.java new file mode 100644 index 000000000..8b1815be3 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Download.java @@ -0,0 +1,20 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.io.IOUtils; +import org.jfrog.build.api.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +public class Download extends DownloadBase { + public Download(String downloadFrom, Map headers, Log log) { + super(downloadFrom, false, headers, log); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = IOUtils.toString(stream, StandardCharsets.UTF_8); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadBase.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadBase.java new file mode 100644 index 000000000..dffda287d --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadBase.java @@ -0,0 +1,49 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +public abstract class DownloadBase extends JFrogService { + private final String DownloadPath; + private final boolean isHead; + private final Map headers; + + protected DownloadBase(String DownloadPath, boolean isHead, Map headers, Log log) { + super(log); + this.DownloadPath = encodeUrl(DownloadPath); + this.isHead = isHead; + this.headers = headers; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + HttpRequestBase request = isHead ? new HttpHead(DownloadPath) : new HttpGet(DownloadPath); + // Explicitly force keep alive + request.setHeader("Connection", "Keep-Alive"); + // Add all required headers to the request + if (headers != null) { + for (Map.Entry entry : headers.entrySet()) { + request.setHeader(entry.getKey(), entry.getValue()); + } + } + return request; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + if (statusCode == HttpStatus.SC_NOT_FOUND) { + throw new FileNotFoundException("Unable to find " + DownloadPath); + } + log.error("Failed to download from '" + DownloadPath + "'"); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadHeaders.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadHeaders.java new file mode 100644 index 000000000..55c79a9f9 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadHeaders.java @@ -0,0 +1,23 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.Header; +import org.jfrog.build.api.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +public class DownloadHeaders extends DownloadBase { + public DownloadHeaders(String downloadFrom, Map headers, Log log) { + super(downloadFrom, true, headers, log); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getHeaders(); + } + + protected void handleEmptyEntity() { + result = getHeaders(); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadToFile.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadToFile.java new file mode 100644 index 000000000..bbebc834f --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/DownloadToFile.java @@ -0,0 +1,43 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.io.IOUtils; +import org.jfrog.build.api.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +public class DownloadToFile extends DownloadBase { + private final String downloadTo; + + public DownloadToFile(String downloadFrom, String downloadTo, Map headers, Log log) { + super(downloadFrom, false, headers, log); + this.downloadTo = downloadTo; + } + + private static File saveInputStreamToFile(InputStream inputStream, String filePath) throws IOException { + // Create file + File dest = new File(filePath); + if (dest.exists()) { + dest.delete(); + } else { + dest.getParentFile().mkdirs(); + } + + // Save InputStream to file + try (FileOutputStream fileOutputStream = new FileOutputStream(dest)) { + IOUtils.copyLarge(inputStream, fileOutputStream); + + return dest; + } catch (IOException e) { + throw new IOException(String.format("Could not create or write to file: %s", dest.getCanonicalPath()), e); + } + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = saveInputStreamToFile(stream, downloadTo); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ExecuteUserPlugin.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ExecuteUserPlugin.java new file mode 100644 index 000000000..8af9852ad --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ExecuteUserPlugin.java @@ -0,0 +1,38 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; +import java.util.Map; + +import static org.jfrog.build.extractor.clientConfiguration.util.UrlUtils.appendParamsToUrl; + +public class ExecuteUserPlugin extends VoidJFrogService { + public static final String EXECUTE_USER_PLUGIN_ENDPOINT = "api/storage/"; + + private final String executionName; + private final Map requestParams; + + public ExecuteUserPlugin(String executionName, Map requestParams, Log logger) { + super(logger); + this.executionName = executionName; + this.requestParams = requestParams; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + StringBuilder urlBuilder = new StringBuilder(EXECUTE_USER_PLUGIN_ENDPOINT).append(executionName).append("?"); + appendParamsToUrl(requestParams, urlBuilder); + return new HttpPost(urlBuilder.toString()); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to execute user plugin."); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetBuildInfo.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetBuildInfo.java new file mode 100644 index 000000000..d2509dc56 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetBuildInfo.java @@ -0,0 +1,39 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.Build; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; +import org.jfrog.build.extractor.clientConfiguration.client.response.GetBuildInfoResponse; + +import java.io.IOException; +import java.io.InputStream; + +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.PublishBuildInfo.getProjectQueryParam; + +public class GetBuildInfo extends JFrogService { + + private final String buildName; + private final String buildNumber; + private final String project; + + public GetBuildInfo(String buildName, String buildNumber, String project, Log logger) { + super(logger); + + this.buildName = buildName; + this.buildNumber = buildNumber; + this.project = project; + } + + @Override + public HttpRequestBase createRequest() { + String apiEndPoint = String.format("%s/%s/%s%s", "api/build", encodeUrl(buildName), encodeUrl(buildNumber), getProjectQueryParam(project)); + return new HttpGet(apiEndPoint); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, GetBuildInfoResponse.class).getBuildInfo(); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetItemLastModified.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetItemLastModified.java new file mode 100644 index 000000000..64e3e86e7 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetItemLastModified.java @@ -0,0 +1,51 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.ItemLastModified; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; + +public class GetItemLastModified extends JFrogService { + public static final String ITEM_LAST_MODIFIED = "api/storage/"; + + private final String path; + + public GetItemLastModified(String path, Log logger) { + super(logger); + this.path = path; + } + + @Override + public HttpRequestBase createRequest() { + return new HttpGet(ITEM_LAST_MODIFIED + path + "?lastModified"); + } + + @Override + protected void handleEmptyEntity() throws IOException { + throw new IOException("The path " + path + " returned empty entity"); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, ItemLastModified.class); + try { + if (result.getLastModified() == 0 || result.getUri() == null) { + throw new IOException("JSON response is missing URI or LastModified fields when requesting info for path " + path); + } + } catch (ParseException e) { + throw new IOException("JSON response is missing URI or LastModified fields when requesting info for path " + path); + } + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed while requesting item info for path: " + path); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetNpmAuth.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetNpmAuth.java new file mode 100644 index 000000000..8055ac877 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetNpmAuth.java @@ -0,0 +1,37 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class GetNpmAuth extends JFrogService { + private static final String GET_NPM_AUTH_ENDPOINT = "api/npm/auth"; + + + public GetNpmAuth(Log log) { + super(log); + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpGet(GET_NPM_AUTH_ENDPOINT); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("npm Auth request failed"); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = new Properties(); + result.load(stream); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetRepositoriesKeys.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetRepositoriesKeys.java new file mode 100644 index 000000000..792c7e558 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetRepositoriesKeys.java @@ -0,0 +1,49 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; +import org.jfrog.build.extractor.clientConfiguration.client.RepositoryType; +import org.jfrog.build.extractor.clientConfiguration.client.response.GetRepositoriesKeyResponse; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class GetRepositoriesKeys extends JFrogService> { + private static final String REPOS_REST_URL = "api/repositories?type="; + + protected final Log log; + RepositoryType repositoryType; + + @SuppressWarnings("unchecked") + public GetRepositoriesKeys(RepositoryType repositoryType, Log logger) { + super(logger); + result = new ArrayList<>(); + this.repositoryType = repositoryType; + log = logger; + } + + @Override + public HttpRequestBase createRequest() { + String endpoint = REPOS_REST_URL + repositoryType.name().toLowerCase(); + HttpGet req = new HttpGet(endpoint); + log.debug("Requesting repositories list from: " + endpoint); + return req; + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + GetRepositoriesKeyResponse localRepositories = getMapper(true).readValue(stream, GetRepositoriesKeyResponse.class); + result = localRepositories.getRepositoriesKey(); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to obtain list of repositories."); + throwException(entity, getStatusCode()); + } +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetStagingStrategy.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetStagingStrategy.java new file mode 100644 index 000000000..0b6bb1298 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetStagingStrategy.java @@ -0,0 +1,49 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import static org.jfrog.build.extractor.clientConfiguration.util.UrlUtils.appendParamsToUrl; + +public class GetStagingStrategy extends JFrogService { + private static final String BUILD_STAGING_STRATEGY_ENDPOINT = "api/plugins/build/staging/"; + private final String strategyName; + private final String buildName; + private final Map requestParams; + + public GetStagingStrategy(String strategyName, String buildName, Map requestParams, Log log) { + super(log); + this.strategyName = strategyName; + this.buildName = buildName; + this.requestParams = requestParams; + result = new HashMap<>(); + } + + @Override + public HttpRequestBase createRequest() throws IOException { + StringBuilder urlBuilder = new StringBuilder(BUILD_STAGING_STRATEGY_ENDPOINT) + .append(encodeUrl(strategyName)).append("?buildName=") + .append(encodeUrl(buildName)).append("&"); + appendParamsToUrl(requestParams, urlBuilder); + return new HttpGet(urlBuilder.toString()); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to obtain staging strategy."); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, Map.class); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetUserPluginInfo.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetUserPluginInfo.java new file mode 100644 index 000000000..f622cdc2c --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/GetUserPluginInfo.java @@ -0,0 +1,40 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GetUserPluginInfo extends JFrogService>> { + public static final String USER_PLUGIN_ENDPOINT = "api/storage/"; + + @SuppressWarnings("unchecked") + public GetUserPluginInfo(Log log) { + super(log); + result = new HashMap<>(); + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpGet(USER_PLUGIN_ENDPOINT); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, TypeFactory.defaultInstance().constructMapType(Map.class, String.class, List.class)); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to obtain user plugin information."); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/IsRepositoryExist.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/IsRepositoryExist.java new file mode 100644 index 000000000..158e533fb --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/IsRepositoryExist.java @@ -0,0 +1,36 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.InputStream; + +public class IsRepositoryExist extends JFrogService { + private static final String REPOS_REST_URL = "api/repositories/"; + + private final String repo; + + public IsRepositoryExist(String repo, Log logger) { + super(logger); + this.repo = repo; + } + + @Override + public HttpRequestBase createRequest() { + return new HttpGet(REPOS_REST_URL + repo); + } + + @Override + protected void setResponse(InputStream stream) { + result = true; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) { + result = statusCode != HttpStatus.SC_BAD_REQUEST; + } +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PromotionUserPlugin.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PromotionUserPlugin.java new file mode 100644 index 000000000..34f148ea7 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PromotionUserPlugin.java @@ -0,0 +1,44 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; +import java.util.Map; + +import static org.jfrog.build.extractor.clientConfiguration.util.UrlUtils.appendParamsToUrl; + + +public class PromotionUserPlugin extends VoidJFrogService { + public static final String PROMOTION_USER_PLUGIN_ENDPOINT = "/api/plugins/build/promote/"; + + private final String promotionName; + private final String buildName; + private final String buildNumber; + private final Map requestParams; + + public PromotionUserPlugin(String promotionName, String buildName, String buildNumber, Map requestParams, Log logger) { + super(logger); + this.promotionName = promotionName; + this.buildName = buildName; + this.buildNumber = buildNumber; + this.requestParams = requestParams; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + StringBuilder urlBuilder = new StringBuilder(PROMOTION_USER_PLUGIN_ENDPOINT).append(promotionName).append("/").append(encodeUrl(buildName)).append("/") + .append(encodeUrl(buildNumber)).append("?"); + appendParamsToUrl(requestParams, urlBuilder); + return new HttpPost(urlBuilder.toString()); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to promote user plugin."); + throwException(entity, statusCode); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PublishBuildInfo.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PublishBuildInfo.java new file mode 100644 index 000000000..ac2c95f76 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/PublishBuildInfo.java @@ -0,0 +1,105 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.Build; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + +public class PublishBuildInfo extends VoidJFrogService { + public static final String BUILD_BROWSE_URL = "/webapp/builds"; + private static final String BUILD_REST_URL = "/api/build"; + public static final String BUILD_BROWSE_PLATFORM_URL = "/ui/builds"; + private static final String BUILD_PROJECT_PARAM = "?project="; + + private final Build buildInfo; + private final String platformUrl; + private String buildInfoJson; + + public PublishBuildInfo(Build buildInfo, String platformUrl, Log logger) { + super(logger); + this.buildInfo = buildInfo; + this.platformUrl = platformUrl; + } + + public static String getProjectQueryParam(String project, String prefix) { + if (StringUtils.isNotEmpty(project)) { + return prefix + encodeUrl(project); + } + return ""; + } + + public static String getProjectQueryParam(String project) { + return getProjectQueryParam(project, BUILD_PROJECT_PARAM); + } + + /** + * Creates a build info link to the published build in JFrog platform (Artifactory V7) + * + * @param platformUrl Base platform URL + * @param buildName Build name of the published build + * @param buildNumber Build number of the published build + * @param timeStamp Timestamp (started date time in milliseconds) of the published build + * @return Link to the published build in JFrog platform e.g. https://myartifactory.com/ui/builds/gradle-cli/1/1619429119501/published + */ + public static String createBuildInfoUrl(String platformUrl, String buildName, String buildNumber, String timeStamp, String project) { + return String.format("%s/%s/%s/%s/%s", platformUrl + BUILD_BROWSE_PLATFORM_URL, encodeUrl(buildName), encodeUrl(buildNumber), timeStamp, "published" + getProjectQueryParam(project)); + } + + /** + * Creates a build info link to the published build in Artifactory (Artifactory V6 or below) + * + * @param artifactoryUrl Base Artifactory URL + * @param buildName Build name of the published build + * @param buildNumber Build number of the published build + * @return Link to the published build in Artifactory e.g. https://myartifactory.com/artifactory/webapp/builds/gradle-cli/1 + */ + public static String createBuildInfoUrl(String artifactoryUrl, String buildName, String buildNumber) { + return String.format("%s/%s/%s", artifactoryUrl + BUILD_BROWSE_URL, encodeUrl(buildName), encodeUrl(buildNumber)); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Could not build the build-info object."); + throwException(entity, getStatusCode()); + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) throws IOException { + if (buildInfo == null) { + return; + } + buildInfoJson = toJsonString(buildInfo); + } + + @Override + public HttpRequestBase createRequest() { + HttpPut request = new HttpPut(BUILD_REST_URL + getProjectQueryParam(buildInfo.getProject())); + StringEntity stringEntity = new StringEntity(buildInfoJson, "UTF-8"); + stringEntity.setContentType("application/vnd.org.jfrog.artifactory+json"); + request.setEntity(stringEntity); + log.info("Deploying build info to: " + BUILD_REST_URL); + return request; + } + + @Override + public Void execute(JFrogHttpClient client) throws IOException { + super.execute(client); + String url; + if (StringUtils.isNotBlank(platformUrl)) { + url = createBuildInfoUrl(platformUrl, buildInfo.getName(), buildInfo.getNumber(), String.valueOf(buildInfo.getStartedMillis()), buildInfo.getProject()); + } else { + url = createBuildInfoUrl(client.getUrl(), buildInfo.getName(), buildInfo.getNumber()); + } + log.info("Build successfully deployed. Browse it in Artifactory under " + url); + return result; + } +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ReportUsage.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ReportUsage.java new file mode 100644 index 000000000..7cd6219bc --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ReportUsage.java @@ -0,0 +1,47 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.ArtifactoryVersion; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; +import org.jfrog.build.extractor.clientConfiguration.util.JsonSerializer; +import org.jfrog.build.extractor.usageReport.UsageReporter; + +import java.io.IOException; + +public class ReportUsage extends VoidJFrogService { + private static final ArtifactoryVersion USAGE_ARTIFACTORY_MIN_VERSION = new ArtifactoryVersion("6.9.0"); + private static final String USAGE_API = "api/system/usage"; + + private final UsageReporter usageReporter; + + public ReportUsage(UsageReporter usageReporter, Log log) { + super(log); + this.usageReporter = usageReporter; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String requestBody = new JsonSerializer().toJSON(usageReporter); + StringEntity entity = new StringEntity(requestBody, "UTF-8"); + entity.setContentType("application/json"); + HttpPost request = new HttpPost(USAGE_API); + request.setEntity(entity); + return request; + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) throws IOException { + Version versionService = new Version(log); + ArtifactoryVersion version = versionService.execute(client); + if (version.isNotFound()) { + throw new IOException("Could not get Artifactory version."); + } + if (!version.isAtLeast(USAGE_ARTIFACTORY_MIN_VERSION)) { + throw new IOException("Usage report is not supported on targeted Artifactory server."); + } + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/RetrievePatternArtifacts.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/RetrievePatternArtifacts.java new file mode 100644 index 000000000..e2c49b5b8 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/RetrievePatternArtifacts.java @@ -0,0 +1,42 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.dependency.BuildPatternArtifacts; +import org.jfrog.build.api.dependency.BuildPatternArtifactsRequest; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; +import org.jfrog.build.extractor.clientConfiguration.util.JsonSerializer; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class RetrievePatternArtifacts extends JFrogService> { + private static final String PATTERN_ARTIFACT_REST_URL = "/api/build/patternArtifacts"; + private final List requests; + + @SuppressWarnings("unchecked") + public RetrievePatternArtifacts(List requests, Log logger) { + super(logger); + this.requests = requests; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + log.info("Retrieving build artifacts report from: " + PATTERN_ARTIFACT_REST_URL); + HttpPost req = new HttpPost(PATTERN_ARTIFACT_REST_URL); + String json = new JsonSerializer>().toJSON(requests); + StringEntity stringEntity = new StringEntity(json); + stringEntity.setContentType("application/vnd.org.jfrog.artifactory+json"); + req.setEntity(stringEntity); + return req; + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, TypeFactory.defaultInstance().constructCollectionLikeType(List.class, BuildPatternArtifacts.class)); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryXrayClient.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ScanBuild.java similarity index 59% rename from build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryXrayClient.java rename to build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ScanBuild.java index c7e55d933..ab837b123 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryXrayClient.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/ScanBuild.java @@ -1,67 +1,59 @@ -package org.jfrog.build.extractor.clientConfiguration.client; +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.NullArgumentException; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.StringEntity; -import org.apache.http.util.EntityUtils; import org.jfrog.build.api.util.Log; -import org.jfrog.build.client.PreemptiveHttpClient; +import org.jfrog.build.client.JFrogHttpClient; import org.jfrog.build.client.artifactoryXrayResponse.ArtifactoryXrayResponse; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; -/** - * Created by romang on 1/1/17. - */ -public class ArtifactoryXrayClient extends ArtifactoryBaseClient { - private static final String SCAN_BUILD_URL = "/api/xray/scanBuild"; - /** - * Retrying to resume the scan 5 times after a stable connection - */ - private static final int XRAY_SCAN_RETRY_CONSECUTIVE_RETRIES = 5; +public class ScanBuild extends JFrogService { /** * Expecting \r\n every 30 seconds */ - private static final int XRAY_SCAN_CONNECTION_TIMEOUT_SECS = 90; - /** - * 30 seconds sleep between retry - */ - private static final int XRAY_SCAN_SLEEP_BETWEEN_RETRIES_MILLIS = 30000; + public static final int XRAY_SCAN_CONNECTION_TIMEOUT_SECS = 90; /** * Fatal error code from Xray */ private static final String XRAY_FATAL_FAIL_STATUS = "-1"; /** - * ArtifactoryXrayClient manages retry mechanism, http-client's mechanism is not required + * Retrying to resume the scan 5 times after a stable connection */ - private static final int HTTP_CLIENT_RETRIES = 0; - - public ArtifactoryXrayClient(String artifactoryUrl, String username, String password, String accessToken, Log logger) { - super(artifactoryUrl, username, password, accessToken, logger); - setConnectionRetries(HTTP_CLIENT_RETRIES); - } - - public ArtifactoryXrayClient(String artifactoryUrl, String username, String password, Log logger) { - this(artifactoryUrl, username, password, StringUtils.EMPTY, logger); + private static final int XRAY_SCAN_RETRY_CONSECUTIVE_RETRIES = 5; + /** + * 30 seconds sleep between retry + */ + private static final int XRAY_SCAN_SLEEP_BETWEEN_RETRIES_MILLIS = 30000; + private static final String SCAN_BUILD_URL = "api/xray/scanBuild"; + private final String buildName; + private final String buildNumber; + private final String context; + private HttpPost request; + + public ScanBuild(String buildName, String buildNumber, String context, Log log) { + super(log); + this.buildName = buildName; + this.buildNumber = buildNumber; + this.context = context; } - public ArtifactoryXrayResponse xrayScanBuild(String buildName, String buildNumber, String context) throws IOException, InterruptedException { + @Override + public HttpRequestBase createRequest() throws IOException { StringEntity entity = new StringEntity("{\"buildName\":\"" + buildName + "\",\"buildNumber\":\"" + buildNumber + "\",\"context\":\"" + context + "\"}"); entity.setContentType("application/json"); - String scanUrl = artifactoryUrl + SCAN_BUILD_URL; - HttpPost httpPost = new HttpPost(scanUrl); + HttpPost request = new HttpPost(SCAN_BUILD_URL); // The scan build operation can take a long time to finish. // To keep the connection open, when Xray starts scanning the build, it starts sending new-lines @@ -69,30 +61,17 @@ public ArtifactoryXrayResponse xrayScanBuild(String buildName, String buildNumbe // connection does not get timed out. // We need make sure the new-lines are not buffered on the nginx and are flushed // as soon as Xray sends them. - httpPost.addHeader("X-Accel-Buffering", "no"); + request.addHeader("X-Accel-Buffering", "no"); - httpPost.setEntity(entity); - return execute(httpPost); + request.setEntity(entity); + this.request = request; + return request; } - /** - * Stable connection is a connection which was connected successfully for at least @stableConnectionMillis. - * - * @param lastConnectionAttemptMillis - * @return - */ - private boolean isStableConnection(long lastConnectionAttemptMillis) { - final long stableConnectionMillis = (XRAY_SCAN_CONNECTION_TIMEOUT_SECS + 10) * 1000; - return lastConnectionAttemptMillis + stableConnectionMillis < System.currentTimeMillis(); - } - - private ArtifactoryXrayResponse parseXrayScanResponse(HttpResponse response) throws IOException { - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new IOException("Artifactory response: " + response.getStatusLine().getReasonPhrase()); - } - + @Override + protected void setResponse(InputStream stream) throws IOException { ObjectMapper mapper = new ObjectMapper(); - String content = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); + String content = IOUtils.toString(stream, StandardCharsets.UTF_8); JsonNode result; try { result = mapper.readTree(content); @@ -101,7 +80,7 @@ private ArtifactoryXrayResponse parseXrayScanResponse(HttpResponse response) thr } } catch (Exception ex) { // Throwing XrayErrorException since the retry-mechanism should not reset the retries-count in such error. - throw new XrayErrorException(String.format("Failed processing scan response: %s\n%s", ex.toString(), content)); + throw new XrayErrorException(String.format("Failed processing scan response: %s\n%s", ex, content)); } if (result.get("errors") != null) { String resultStr = result.get("errors").toString(); @@ -113,59 +92,65 @@ private ArtifactoryXrayResponse parseXrayScanResponse(HttpResponse response) thr throw new XrayErrorException("Artifactory response: " + resultStr); } mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - return mapper.treeToValue(result, ArtifactoryXrayResponse.class); + this.result = mapper.treeToValue(result, ArtifactoryXrayResponse.class); } - private ArtifactoryXrayResponse execute(HttpRequestBase httpRequest) throws InterruptedException, IOException { - PreemptiveHttpClient client = httpClient.getHttpClient(XRAY_SCAN_CONNECTION_TIMEOUT_SECS); + + @Override + public ArtifactoryXrayResponse execute(JFrogHttpClient client) throws IOException { int retryNum = 0; long lastConnectionAttemptMillis = 0; - HttpEntity entity = null; while (true) { - try (CloseableHttpResponse response = client.execute(httpRequest)){ - entity = response.getEntity(); + try { lastConnectionAttemptMillis = System.currentTimeMillis(); retryNum++; - return parseXrayScanResponse(response); + return super.execute(client); } catch (XrayErrorException e) { handleException(retryNum, e); } catch (IOException e) { if (isStableConnection(lastConnectionAttemptMillis)) { // Interruption may happen when build is aborted in the CI Server. if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException("Operation interrupted."); + throw new IOException("Operation interrupted."); } retryNum = 0; continue; } handleException(retryNum, e); } finally { - releaseResponse(httpRequest, entity); + request.releaseConnection(); } } } - private void releaseResponse(HttpRequestBase httpRequest, HttpEntity entity) { - EntityUtils.consumeQuietly(entity); - httpRequest.releaseConnection(); + /** + * Stable connection is a connection which was connected successfully for at least @stableConnectionMillis. + * + */ + private boolean isStableConnection(long lastConnectionAttemptMillis) { + final long stableConnectionMillis = (XRAY_SCAN_CONNECTION_TIMEOUT_SECS + 10) * 1000; + return lastConnectionAttemptMillis + stableConnectionMillis < System.currentTimeMillis(); } - private void handleException(int retryNum, IOException e) throws InterruptedException, IOException { + private void handleException(int retryNum, IOException e) throws IOException { if (XRAY_SCAN_RETRY_CONSECUTIVE_RETRIES <= retryNum) { throw e; } log.warn("Xray scan connection lost: " + e.getMessage() + ", attempting to reconnect..."); // Sleeping before trying to reconnect. - Thread.sleep(XRAY_SCAN_SLEEP_BETWEEN_RETRIES_MILLIS); + try { + Thread.sleep(XRAY_SCAN_SLEEP_BETWEEN_RETRIES_MILLIS); + } catch (InterruptedException interruptedException) { + throw new IOException(interruptedException.getMessage()); + } } /** * Private exception class, signals that Xray-response returned from Artifactory contained an error. */ - private class XrayErrorException extends IOException { + private static class XrayErrorException extends IOException { private XrayErrorException(String message) { super(message); } } } - diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByAql.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByAql.java new file mode 100644 index 000000000..0ac6e318c --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByAql.java @@ -0,0 +1,42 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.search.AqlSearchResult; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; + +public class SearchArtifactsByAql extends JFrogService { + private static final String SEARCH_ARTIFACT_BY_AQL_ENDPOINT = "api/search/aql"; + + private final String aql; + + public SearchArtifactsByAql(String aql, Log log) { + super(log); + this.aql = aql; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + HttpPost request = new HttpPost(SEARCH_ARTIFACT_BY_AQL_ENDPOINT); + StringEntity entity = new StringEntity(aql); + request.setEntity(entity); + return request; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to search artifact by the aql '" + aql + "'"); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(true).readValue(stream, AqlSearchResult.class); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByPattern.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByPattern.java new file mode 100644 index 000000000..268182ab6 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByPattern.java @@ -0,0 +1,38 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.dependency.PatternResultFileSet; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; + +public class SearchArtifactsByPattern extends JFrogService { + private static final String SEARCH_ARTIFACT_BY_PATTERN_ENDPOINT = "api/search/pattern?pattern="; + + private final String pattern; + + public SearchArtifactsByPattern(String pattern, Log log) { + super(log); + this.pattern = pattern; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpGet(SEARCH_ARTIFACT_BY_PATTERN_ENDPOINT + pattern); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to search artifact by the pattern '" + pattern + "'"); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(false).readValue(stream, PatternResultFileSet.class); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByProperties.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByProperties.java new file mode 100644 index 000000000..effe3af45 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SearchArtifactsByProperties.java @@ -0,0 +1,41 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.dependency.PropertySearchResult; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; + +public class SearchArtifactsByProperties extends JFrogService { + private static final String SEARCH_ARTIFACT_BY_PROPERTIES_ENDPOINT = "api/search/prop?"; + + private final String properties; + + public SearchArtifactsByProperties(String properties, Log log) { + super(log); + this.properties = properties; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String replacedProperties = StringUtils.replaceEach(properties, new String[]{";", "+"}, new String[]{"&", ""}); + String url = SEARCH_ARTIFACT_BY_PROPERTIES_ENDPOINT + replacedProperties; + return new HttpGet(url); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to search artifact by the properties '" + properties + "'"); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(false).readValue(stream, PropertySearchResult.class); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendBuildRetention.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendBuildRetention.java new file mode 100644 index 000000000..fffc13b1b --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendBuildRetention.java @@ -0,0 +1,65 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.BuildRetention; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.PublishBuildInfo.getProjectQueryParam; +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + +public class SendBuildRetention extends VoidJFrogService { + private static final String RETENTION_REST_URL = "api/build/retention/"; + private final BuildRetention buildRetention; + private final String buildName; + private final String project; + private final boolean async; + + public SendBuildRetention(BuildRetention buildRetention, String buildName, String project, boolean async, Log logger) { + super(logger); + this.buildRetention = buildRetention; + this.buildName = encodeUrl(buildName); + this.project = project; + this.async = async; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + log.info(createBuildRetentionLogMsg(buildRetention, async)); + log.debug(toJsonString(buildRetention)); + String url = RETENTION_REST_URL + buildName + "?async=" + async + getProjectQueryParam(project, "&project="); + return new HttpPost(url); + } + + private String createBuildRetentionLogMsg(BuildRetention buildRetention, boolean async) { + StringBuilder strBuilder = new StringBuilder().append("Sending"); + + if (async) { + strBuilder.append(" async"); + } + + strBuilder.append(" request for build retention"); + + if (buildRetention.isDeleteBuildArtifacts()) { + strBuilder.append(", deleting build artifacts"); + } + + if (buildRetention.getCount() != -1) { + strBuilder.append(", max number of builds to store: ").append(buildRetention.getCount()); + } + + if (buildRetention.getMinimumBuildDate() != null) { + strBuilder.append(", min build date: ").append(buildRetention.getMinimumBuildDate()); + } + + if (!buildRetention.getBuildNumbersNotToBeDiscarded().isEmpty()) { + strBuilder.append(", build numbers not to be discarded: ").append(buildRetention.getBuildNumbersNotToBeDiscarded()); + } + strBuilder.append("."); + + return strBuilder.toString(); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendModuleInfo.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendModuleInfo.java new file mode 100644 index 000000000..fe384ec0d --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SendModuleInfo.java @@ -0,0 +1,44 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.Build; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.PublishBuildInfo.getProjectQueryParam; +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + +public class SendModuleInfo extends VoidJFrogService { + public static final String APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON = "application/vnd.org.jfrog.artifactory+json"; + private static final String SEND_MODULE_INFO_ENDPOINT = "/api/build/append/"; + private final Build build; + + public SendModuleInfo(Build build, Log logger) { + super(logger); + this.build = build; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String url = SEND_MODULE_INFO_ENDPOINT + encodeUrl(build.getName()) + "/" + + encodeUrl(build.getNumber()) + getProjectQueryParam(build.getProject()); + HttpPost request = new HttpPost(url); + String modulesAsJsonString = toJsonString(build.getModules()); + StringEntity stringEntity = new StringEntity(modulesAsJsonString, "UTF-8"); + stringEntity.setContentType(APPLICATION_VND_ORG_JFROG_ARTIFACTORY_JSON); + request.setEntity(stringEntity); + log.info("Deploying build descriptor to: " + request.getURI().toString()); + return request; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Could not publish build-info modules"); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SetProperties.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SetProperties.java new file mode 100644 index 000000000..c4444efb7 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/SetProperties.java @@ -0,0 +1,75 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import com.google.common.collect.ArrayListMultimap; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; +import org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils; + +import java.io.IOException; + +public class SetProperties extends VoidJFrogService { + public static final String SET_PROPERTIES_ENDPOINT = "api/storage/"; + + private final String relativePath; + private final String properties; + private final boolean encodeProperties; + + public SetProperties(String relativePath, String properties, boolean encodeProperties, Log log) { + super(log); + this.relativePath = relativePath; + this.properties = properties; + this.encodeProperties = encodeProperties; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + String requestUrl = SET_PROPERTIES_ENDPOINT + encodeUrl(StringUtils.stripEnd(relativePath, "/") + "?properties="); + if (encodeProperties) { + requestUrl += DeploymentUrlUtils.buildMatrixParamsString(mapPropsString(properties), true); + } else { + requestUrl += properties; + } + return new HttpPut(requestUrl); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to set properties to '" + relativePath + "'"); + throwException(entity, getStatusCode()); + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) throws IOException { + for (String prop : properties.trim().split(";")) { + if (prop.isEmpty()) { + continue; + } + + String key = StringUtils.substringBefore(prop, "="); + if (key.isEmpty()) { + throw new IOException("Setting properties: Every property must have a key."); + } + + String values = StringUtils.substringAfter(prop, "="); + // Verify values aren't empty nor commas only + if (values.isEmpty() || StringUtils.countMatches(values, ",") == values.length()) { + throw new IOException("Setting properties: Every property must have at least one value."); + } + } + } + + private ArrayListMultimap mapPropsString(String props) { + ArrayListMultimap propsMap = ArrayListMultimap.create(); + String[] propsList = props.split(";"); + for (String prop : propsList) { + String[] propParts = prop.split("="); + propsMap.put(propParts[0], propParts[1]); + } + return propsMap; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/StageBuild.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/StageBuild.java new file mode 100644 index 000000000..2aa632800 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/StageBuild.java @@ -0,0 +1,55 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.jfrog.build.api.release.Promotion; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + +public class StageBuild extends VoidJFrogService { + private static final String BUILD_STAGING_STRATEGY_ENDPOINT = "api/build/promote/"; + private final String buildName; + private final String buildNumber; + private final Promotion promotion; + + public StageBuild(String buildName, String buildNumber, Promotion promotion, Log logger) { + super(logger); + this.buildName = buildName; + this.buildNumber = buildNumber; + this.promotion = promotion; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + HttpPost request = new HttpPost(BUILD_STAGING_STRATEGY_ENDPOINT + encodeUrl(buildName) + "/" + encodeUrl(buildNumber)); + StringEntity stringEntity = new StringEntity(toJsonString(promotion)); + stringEntity.setContentType("application/vnd.org.jfrog.artifactory.build.PromotionRequest+json"); + request.setEntity(stringEntity); + log.info("Promotion build " + buildName + ", #" + buildNumber); + return request; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Promotion failed."); + throwException(entity, getStatusCode()); + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) { + if (StringUtils.isBlank(buildName)) { + throw new IllegalArgumentException("Build name is required for promotion."); + } + if (StringUtils.isBlank(buildNumber)) { + throw new IllegalArgumentException("Build number is required for promotion."); + } + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/UpdateFileProperty.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/UpdateFileProperty.java new file mode 100644 index 000000000..10e8d8796 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/UpdateFileProperty.java @@ -0,0 +1,32 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.clientConfiguration.client.VoidJFrogService; + +import java.io.IOException; + +public class UpdateFileProperty extends VoidJFrogService { + private static final String UPDATE_FILE_PROPERTY_ENDPOINT = "api/storage/"; + private final String itemPath; + private final String properties; + + public UpdateFileProperty(String itemPath, String properties, Log logger) { + super(logger); + this.itemPath = itemPath; + this.properties = properties; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + return new HttpPut(UPDATE_FILE_PROPERTY_ENDPOINT + encodeUrl(itemPath) + "?properties=" + encodeUrl(properties)); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed while trying to set properties on docker layer."); + throwException(entity, getStatusCode()); + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Upload.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Upload.java new file mode 100644 index 000000000..c8308fac8 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Upload.java @@ -0,0 +1,155 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.FileEntity; +import org.apache.http.protocol.HTTP; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.ArtifactoryUploadResponse; +import org.jfrog.build.client.ArtifactoryVersion; +import org.jfrog.build.client.JFrogHttpClient; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; +import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; +import org.jfrog.build.extractor.clientConfiguration.util.DeploymentUrlUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration.DEFAULT_MIN_CHECKSUM_DEPLOY_SIZE_KB; + +public class Upload extends JFrogService { + public static final String SHA1_HEADER_NAME = "X-Checksum-Sha1"; + public static final String MD5_HEADER_NAME = "X-Checksum-Md5"; + private final DeployDetails details; + private final String logPrefix; + private final Integer minChecksumDeploySizeKb; + private boolean isExplode; + + public Upload(DeployDetails details, String logPrefix, Integer minChecksumDeploySizeKb, Log logger) { + super(logger); + this.minChecksumDeploySizeKb = minChecksumDeploySizeKb; + this.details = details; + this.logPrefix = logPrefix == null ? "" : logPrefix + " "; + } + + @Override + public HttpRequestBase createRequest() throws IOException { + HttpPut request = createHttpPutMethod(details); + log.info(logPrefix + "Deploying artifact: " + request.getURI().toString()); + // add the 100 continue directive + request.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE); + if (details.isExplode()) { + this.isExplode = true; + request.addHeader("X-Explode-Archive", "true"); + } + FileEntity fileEntity = new FileEntity(details.getFile(), "binary/octet-stream"); + request.setEntity(fileEntity); + return request; + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + log.error("Failed to upload file"); + throwException(entity, getStatusCode()); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + if (!isExplode) { + result = getMapper(false).readValue(stream, ArtifactoryUploadResponse.class); + } + } + + @Override + public ArtifactoryUploadResponse execute(JFrogHttpClient client) throws IOException { + ArtifactoryUploadResponse response = tryChecksumUpload(client); + if (response != null) { + // Checksum deploy was performed: + return response; + } + + return super.execute(client); + } + + private ArtifactoryUploadResponse tryChecksumUpload(JFrogHttpClient client) { + try { + TryChecksumUpload tryChecksumUploadService = new TryChecksumUpload(details, logPrefix, minChecksumDeploySizeKb, log); + return tryChecksumUploadService.execute(client); + } catch (IOException e) { + log.debug("Failed artifact checksum deploy of file " + details.getArtifactPath() + " : " + details.getSha1()); + } + return null; + } + + private HttpPut createHttpPutMethod(DeployDetails details) throws IOException { + StringBuilder deploymentPathBuilder = new StringBuilder().append(buildDefaultUploadPath(details)); + deploymentPathBuilder.append(DeploymentUrlUtils.buildMatrixParamsString(details.getProperties(), true)); + HttpPut httpPut = new HttpPut(deploymentPathBuilder.toString()); + httpPut.addHeader(SHA1_HEADER_NAME, details.getSha1()); + httpPut.addHeader(MD5_HEADER_NAME, details.getMd5()); + log.debug("Full Artifact Http path: " + httpPut + "\n@Http Headers: " + Arrays.toString(httpPut.getAllHeaders())); + return httpPut; + } + + private String buildDefaultUploadPath(DeployDetails details) { + List pathComponents = new ArrayList<>(); + pathComponents.add(DeploymentUrlUtils.encodePath(details.getTargetRepository())); + pathComponents.add(DeploymentUrlUtils.encodePath(details.getArtifactPath())); + return StringUtils.join(pathComponents, "/"); + } + + private class TryChecksumUpload extends JFrogService { + private final DeployDetails details; + private final String logPrefix; + private final Integer minChecksumDeploySizeKb; + + private TryChecksumUpload(DeployDetails details, String logPrefix, Integer minChecksumDeploySizeKb, Log logger) { + super(logger); + this.details = details; + this.logPrefix = logPrefix; + this.minChecksumDeploySizeKb = minChecksumDeploySizeKb != null ? minChecksumDeploySizeKb : DEFAULT_MIN_CHECKSUM_DEPLOY_SIZE_KB; + } + + @Override + protected void ensureRequirements(JFrogHttpClient client) throws IOException { + Version versionService = new Version(log); + ArtifactoryVersion version = versionService.execute(client); + // Artifactory 2.5.1+ has efficient checksum deployment (checks if the artifact already exists by it's checksum) + if (!version.isAtLeast(new ArtifactoryVersion("2.5.1"))) { + throw new IOException("Artifactory below 2.5.0 doesnt have efficient checksum deployment"); + } + } + + @Override + public HttpRequestBase createRequest() throws IOException { + // Try checksum upload only on file size equal or greater than 'minChecksumDeploySizeKb' + long fileLength = details.getFile().length(); + if (fileLength < minChecksumDeploySizeKb * 1024) { + log.debug("Skipping checksum deploy of file size " + fileLength + " bytes, falling back to regular deployment."); + throw new IOException(); + } + + if (details.isExplode()) { + log.debug("Skipping checksum deploy due to explode file request."); + throw new IOException(); + } + + HttpPut request = createHttpPutMethod(details); + log.info(logPrefix + "Deploying artifact: " + request.getURI().toString()); + // activate checksum deploy + request.addHeader("X-Checksum-Deploy", "true"); + + return request; + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + result = getMapper(false).readValue(stream, ArtifactoryUploadResponse.class); + } + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Version.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Version.java new file mode 100644 index 000000000..abaa50b4c --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/artifactory/services/Version.java @@ -0,0 +1,48 @@ +package org.jfrog.build.extractor.clientConfiguration.client.artifactory.services; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.jfrog.build.api.util.Log; +import org.jfrog.build.client.ArtifactoryVersion; +import org.jfrog.build.extractor.clientConfiguration.client.JFrogService; + +import java.io.IOException; +import java.io.InputStream; + +public class Version extends JFrogService { + private static final String VERSION_REST_URL = "api/system/version"; + private final Log log; + + public Version(Log logger) { + super(logger); + log = logger; + result = ArtifactoryVersion.NOT_FOUND; + } + + @Override + public HttpRequestBase createRequest() { + return new HttpGet(VERSION_REST_URL); + } + + @Override + protected void setResponse(InputStream stream) throws IOException { + JsonNode result = getMapper(false).readTree(stream); + log.debug("Version result: " + result); + String version = result.get("version").asText(); + JsonNode addonsNode = result.get("addons"); + boolean hasAddons = (addonsNode != null) && addonsNode.iterator().hasNext(); + this.result = new ArtifactoryVersion(version, hasAddons); + } + + @Override + protected void handleUnsuccessfulResponse(HttpEntity entity) throws IOException { + if (statusCode == HttpStatus.SC_NOT_FOUND) { + result = ArtifactoryVersion.NOT_FOUND; + } else { + throwException(entity, getStatusCode()); + } + } +} \ No newline at end of file diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetBuildInfoResponse.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetBuildInfoResponse.java new file mode 100644 index 000000000..7388b16c0 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetBuildInfoResponse.java @@ -0,0 +1,15 @@ +package org.jfrog.build.extractor.clientConfiguration.client.response; + +import org.jfrog.build.api.Build; + +public class GetBuildInfoResponse { + private Build buildInfo; + + public Build getBuildInfo() { + return buildInfo; + } + + public void setBuildInfo(Build buildInfo) { + this.buildInfo = buildInfo; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetRepositoriesKeyResponse.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetRepositoriesKeyResponse.java new file mode 100644 index 000000000..c3c0fa812 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/client/response/GetRepositoriesKeyResponse.java @@ -0,0 +1,32 @@ +package org.jfrog.build.extractor.clientConfiguration.client.response; + +import java.util.List; +import java.util.stream.Collectors; + +public class GetRepositoriesKeyResponse { + private List results; + + public List getResults() { + return results; + } + + public void setResults(List key) { + this.results = key; + } + + public List getRepositoriesKey() { + return results.stream().map(LocalRepository::getKey).collect(Collectors.toList()); + } + + public static class LocalRepository { + private String key; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AntPatternsDependenciesHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AntPatternsDependenciesHelper.java index a06845ac8..b77d75de8 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AntPatternsDependenciesHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AntPatternsDependenciesHelper.java @@ -49,7 +49,7 @@ public List retrievePublishedDependencies(String resolvePattern) thr } private Set collectArtifactsToDownload(List patternLines) - throws IOException, InterruptedException { + throws IOException { Set downloadableArtifacts = new HashSet<>(); for (String patternLine : patternLines) { DependencyPattern dependencyPattern = PatternFactory.create(patternLine); @@ -80,7 +80,7 @@ private Set performPropertySearch(DependencyPattern depend Set downloadableArtifacts = new HashSet<>(); String pattern = dependencyPattern.getPattern(); String matrixParams = dependencyPattern.getMatrixParams(); - PropertySearchResult propertySearchResult = downloader.getClient().searchArtifactsByProperties(matrixParams); + PropertySearchResult propertySearchResult = downloader.getArtifactoryManager().searchArtifactsByProperties(matrixParams); List filteredEntries = filterResultEntries( propertySearchResult.getResults(), pattern); log.info("Found " + filteredEntries.size() + " dependencies by doing a property search."); @@ -102,7 +102,7 @@ private List filterResultEntries(List performPatternSearch(DependencyPattern dependencyPattern) throws IOException { Set downloadableArtifacts = new HashSet<>(); String pattern = dependencyPattern.getPattern(); - PatternResultFileSet fileSet = downloader.getClient().searchArtifactsByPattern(pattern); + PatternResultFileSet fileSet = downloader.getArtifactoryManager().searchArtifactsByPattern(pattern); Set filesToDownload = fileSet.getFiles(); log.info("Found " + filesToDownload.size() + " dependencies by doing a pattern search."); for (String fileToDownload : filesToDownload) { diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AqlHelperBase.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AqlHelperBase.java index c7530b081..756151ea8 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AqlHelperBase.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/AqlHelperBase.java @@ -4,7 +4,7 @@ import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import java.io.IOException; @@ -17,7 +17,7 @@ public class AqlHelperBase { protected static final String DELIMITER = "/"; protected static final String ESCAPE_CHAR = "\\"; - protected ArtifactoryDependenciesClient client; + protected ArtifactoryManager artifactoryManager; private Log log; protected String queryBody; protected String includeFields; @@ -25,8 +25,8 @@ public class AqlHelperBase { protected String buildName; protected String buildNumber; - AqlHelperBase(ArtifactoryDependenciesClient client, Log log, FileSpec file) throws IOException { - this.client = client; + AqlHelperBase(ArtifactoryManager artifactoryManager, Log log, FileSpec file) throws IOException { + this.artifactoryManager = artifactoryManager; this.log = log; convertFileSpecToAql(file); } @@ -34,7 +34,7 @@ public class AqlHelperBase { protected void buildQueryAdditionalParts(FileSpec file) throws IOException { this.buildName = getBuildName(file.getBuild()); // AQL doesn't support projects. - this.buildNumber = getBuildNumber(client, buildName, file.getBuild(), null); + this.buildNumber = getBuildNumber(artifactoryManager, buildName, file.getBuild(), null); this.querySuffix = buildQuerySuffix(file.getSortBy(), file.getSortOrder(), file.getOffset(), file.getLimit()); this.includeFields = buildIncludeQueryPart(file.getSortBy(), querySuffix); } @@ -47,7 +47,7 @@ protected void convertFileSpecToAql(FileSpec file) throws IOException { public List run() throws IOException { String aql = "items.find(" + queryBody + ")" + includeFields + querySuffix; log.debug("Searching Artifactory using AQL query:\n" + aql); - AqlSearchResult aqlSearchResult = client.searchArtifactsByAql(aql); + AqlSearchResult aqlSearchResult = artifactoryManager.searchArtifactsByAql(aql); List queryResults = aqlSearchResult.getResults(); List results = filterResult(queryResults); @@ -70,7 +70,7 @@ protected static String getBuildName(String build) { return buildName.endsWith(ESCAPE_CHAR) ? build : buildName; } - protected String getBuildNumber(ArtifactoryDependenciesClient client, String buildName, String build, String project) throws IOException { + protected String getBuildNumber(ArtifactoryManager client, String buildName, String build, String project) throws IOException { String buildNumber = ""; if (StringUtils.isNotBlank(buildName)) { if (!build.startsWith(buildName)) { @@ -85,7 +85,7 @@ protected String getBuildNumber(ArtifactoryDependenciesClient client, String bui // Remove the escape chars before the delimiters buildNumber = buildNumber.replace(ESCAPE_CHAR + DELIMITER, DELIMITER); } - String retrievedBuildNumber = client.getLatestBuildNumberFromArtifactory(buildName, buildNumber, project); + String retrievedBuildNumber = client.getLatestBuildNumber(buildName, buildNumber, project); if (retrievedBuildNumber == null) { logBuildNotFound(buildName, buildNumber); } @@ -246,7 +246,7 @@ private Map fetchBuildArtifactsSha1() throws IOException { String includeSha1Field = ".include(\"name\",\"repo\",\"path\",\"actual_sha1\")"; String buildAql = createAqlQueryForBuild(includeSha1Field); log.debug("Searching Artifactory for build's checksums using AQL query:\n" + buildAql); - AqlSearchResult aqlSearchResult = client.searchArtifactsByAql(buildAql); + AqlSearchResult aqlSearchResult = artifactoryManager.searchArtifactsByAql(buildAql); return extractSha1FromAqlResponse(aqlSearchResult.getResults()); } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/ArtifactorySearcher.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/ArtifactorySearcher.java index 9509a1f77..8890b3edd 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/ArtifactorySearcher.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/ArtifactorySearcher.java @@ -2,18 +2,18 @@ import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import java.io.IOException; import java.util.List; class ArtifactorySearcher { - private ArtifactoryDependenciesClient client; - private Log log; + private final ArtifactoryManager artifactoryManager; + private final Log log; - ArtifactorySearcher(ArtifactoryDependenciesClient client, Log log) { - this.client = client; + ArtifactorySearcher(ArtifactoryManager artifactoryManager, Log log) { + this.artifactoryManager = artifactoryManager; this.log = log; } @@ -23,15 +23,15 @@ List SearchByFileSpec(FileSpec file) throws IOExcep log.info("Searching for artifacts..."); switch (file.getSpecType()) { case PATTERN: { - aqlHelper = new PatternAqlHelper(client, log, file); + aqlHelper = new PatternAqlHelper(artifactoryManager, log, file); break; } case BUILD: { - aqlHelper = new BuildAqlHelper(client, log, file); + aqlHelper = new BuildAqlHelper(artifactoryManager, log, file); break; } case AQL: { - aqlHelper = new AqlHelperBase(client, log, file); + aqlHelper = new AqlHelperBase(artifactoryManager, log, file); break; } } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildAqlHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildAqlHelper.java index 5c41739ab..e3ddc0e69 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildAqlHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildAqlHelper.java @@ -2,7 +2,7 @@ import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import java.io.IOException; @@ -11,8 +11,8 @@ public class BuildAqlHelper extends AqlHelperBase { - BuildAqlHelper(ArtifactoryDependenciesClient client, Log log, FileSpec file) throws IOException { - super(client, log, file); + BuildAqlHelper(ArtifactoryManager artifactoryManager, Log log, FileSpec file) throws IOException { + super(artifactoryManager, log, file); } @Override @@ -22,7 +22,7 @@ protected void convertFileSpecToAql(FileSpec file) throws IOException { } @Override - protected List filterResult(List queryResults) throws IOException { + protected List filterResult(List queryResults) { Map buildArtifactsSha1 = extractSha1FromAqlResponse(queryResults); return filterAqlSearchResultsByBuild(queryResults, buildArtifactsSha1, buildName, buildNumber); } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildDependenciesHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildDependenciesHelper.java index d23b93ef4..cc73e9bc2 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildDependenciesHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/BuildDependenciesHelper.java @@ -59,7 +59,7 @@ public List retrieveBuildDependencies(String resolvePattern) th log.info("Beginning to resolve Build Info build dependencies."); Map>> buildDependencies = getBuildDependencies(patternLines); List artifactsRequests = toArtifactsRequests(buildDependencies); - List artifactsResponses = downloader.getClient().retrievePatternArtifacts( + List artifactsResponses = downloader.getArtifactoryManager().retrievePatternArtifacts( artifactsRequests); Set result = new HashSet<>(); downloader.download(collectArtifactsToDownload(buildDependencies, artifactsRequests, artifactsResponses, result)); diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloader.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloader.java index 03fa5ada4..5250b7aca 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloader.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloader.java @@ -2,7 +2,7 @@ import org.jfrog.build.api.Dependency; import org.jfrog.build.api.dependency.DownloadableArtifact; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.IOException; import java.io.InputStream; @@ -18,7 +18,7 @@ */ public interface DependenciesDownloader { - ArtifactoryDependenciesClient getClient(); + ArtifactoryManager getArtifactoryManager(); List download(Set downloadableArtifacts) throws IOException; diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderHelper.java index d1a79c6b8..45fbb0454 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderHelper.java @@ -9,26 +9,25 @@ import org.apache.commons.lang.mutable.MutableBoolean; import org.apache.http.Header; import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.util.EntityUtils; import org.jfrog.build.api.Dependency; import org.jfrog.build.api.builder.DependencyBuilder; import org.jfrog.build.api.dependency.DownloadableArtifact; import org.jfrog.build.api.dependency.pattern.PatternType; import org.jfrog.build.api.search.AqlSearchResult; +import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; import org.jfrog.build.api.util.ZipUtils; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import org.jfrog.build.extractor.clientConfiguration.util.spec.Spec; import java.io.*; +import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.regex.Pattern; -import static org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient.MD5_HEADER_NAME; -import static org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient.SHA1_HEADER_NAME; +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.Upload.MD5_HEADER_NAME; +import static org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.Upload.SHA1_HEADER_NAME; /** * Helper class for downloading dependencies @@ -56,8 +55,8 @@ public DependenciesDownloaderHelper(DependenciesDownloader downloader, Log log) this.log = log; } - public DependenciesDownloaderHelper(ArtifactoryDependenciesClient client, String workingDirectory, Log log) { - this.downloader = new DependenciesDownloaderImpl(client, workingDirectory, log); + public DependenciesDownloaderHelper(ArtifactoryManager artifactoryManager, String workingDirectory, Log log) { + this.downloader = new DependenciesDownloaderImpl(artifactoryManager, workingDirectory, log); this.log = log; } @@ -70,7 +69,7 @@ public DependenciesDownloaderHelper(ArtifactoryDependenciesClient client, String * @throws IOException in case of IO error */ public List downloadDependencies(Spec downloadSpec) throws IOException { - ArtifactorySearcher searcher = new ArtifactorySearcher(downloader.getClient(), log); + ArtifactorySearcher searcher = new ArtifactorySearcher(downloader.getArtifactoryManager(), log); Set downloadableArtifacts; List searchResults; List resolvedDependencies = new ArrayList<>(); @@ -111,8 +110,7 @@ private Set fetchDownloadableArtifactsFromResult(List downloadableArtifacts = new HashSet<>(); for (AqlSearchResult.SearchEntry searchEntry : searchResults) { String path = searchEntry.getPath().equals(".") ? "" : searchEntry.getPath() + "/"; - DownloadableArtifact downloadableArtifact = new DownloadableArtifact(StringUtils.stripEnd(downloader.getClient().getArtifactoryUrl(), "/") + "/" + - searchEntry.getRepo(), target, path + searchEntry.getName(), "", "", PatternType.NORMAL); + DownloadableArtifact downloadableArtifact = new DownloadableArtifact(searchEntry.getRepo(), target, path + searchEntry.getName(), "", "", PatternType.NORMAL); downloadableArtifact.setExplode(explode); downloadableArtifacts.add(downloadableArtifact); } @@ -172,7 +170,6 @@ private void removeUnusedArtifactsFromLocal(Set downloadab * * @param downloadableArtifact download recipe * @return artifact dependency - * @throws IOException */ private Dependency downloadArtifact(DownloadableArtifact downloadableArtifact) throws IOException { String filePath = downloadableArtifact.getFilePath(); @@ -197,7 +194,6 @@ private Dependency downloadArtifact(DownloadableArtifact downloadableArtifact) t * @param uriWithParams full artifact uri with matrix params * @param filePath the path to file in file system * @return artifact dependency - * @throws IOException */ Dependency downloadArtifact(DownloadableArtifact downloadableArtifact, ArtifactMetaData artifactMetaData, String uriWithParams, String filePath) throws IOException { String fileDestination = downloader.getTargetDir(downloadableArtifact.getTargetDirPath(), @@ -229,11 +225,12 @@ Dependency downloadArtifact(DownloadableArtifact downloadableArtifact, ArtifactM } } - protected Map downloadFile(String uriWithParams, String fileDestination) throws IOException { - try (CloseableHttpResponse httpResponse = downloader.getClient().downloadArtifact(uriWithParams)) { - try (InputStream inputStream = httpResponse.getEntity().getContent()) { - return downloader.saveDownloadedFile(inputStream, fileDestination); - } + protected Map downloadFile(String downloadPath, String fileDestination) throws IOException { + File downloadedFile = downloader.getArtifactoryManager().downloadToFile(downloadPath, fileDestination); + try { + return FileChecksumCalculator.calculateChecksums(downloadedFile, MD5_ALGORITHM_NAME, SHA1_ALGORITHM_NAME); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(String.format("Could not find checksum algorithm: %s", e.getLocalizedMessage()), e); } } @@ -262,7 +259,7 @@ protected Map downloadFileConcurrently(final String uriWithParam } } - private String[] doConcurrentDownload(long fileSize, final String uriWithParams, String tempPath) + private String[] doConcurrentDownload(long fileSize, final String downloadPath, String tempPath) throws Exception { final MutableBoolean errorOccurred = new MutableBoolean(false); String[] downloadedFilesPaths = new String[CONCURRENT_DOWNLOAD_THREADS]; @@ -275,16 +272,14 @@ private String[] doConcurrentDownload(long fileSize, final String uriWithParams, final Map headers = new HashMap<>(); headers.put(HttpHeaders.RANGE, "bytes=" + start + "-" + end); - final String downloadPath = tempPath + String.valueOf(i); - downloadedFilesPaths[i] = downloadPath; - workers[i] = new Thread(new Runnable() { - public void run() { - try { - saveRequestToFile(uriWithParams, downloadPath, headers); - } catch (Exception e) { - errorOccurred.setValue(true); - printErrorToLog(e, downloadPath, uriWithParams); - } + final String fileDestination = tempPath + i; + downloadedFilesPaths[i] = fileDestination; + workers[i] = new Thread(() -> { + try { + downloader.getArtifactoryManager().downloadToFile(downloadPath, fileDestination, headers); + } catch (Exception e) { + errorOccurred.setValue(true); + printErrorToLog(e, fileDestination, downloadPath); } }); workers[i].setName("downloader_" + i); @@ -300,28 +295,12 @@ public void run() { // Check if error occurred while downloading if (errorOccurred.booleanValue()) { - throw new Exception(String.format("Error occurred while downloading %s, please refer to logs for more information", uriWithParams)); + throw new Exception(String.format("Error occurred while downloading %s, please refer to logs for more information", downloadPath)); } return downloadedFilesPaths; } - /** - * Executes a GET request to download files and saves the result to the file system. - * Used by the downloading threads of concurrentDownloadedArtifact. - * - * @param uriWithParams the request uri - * @param fileDestination location to save the downloaded file to - * @param headers additional headers for the request - */ - private void saveRequestToFile(String uriWithParams, String fileDestination, Map headers) throws IOException { - try (CloseableHttpResponse httpResponse = downloader.getClient().downloadArtifact(uriWithParams, headers)) { - try (InputStream inputStream = httpResponse.getEntity().getContent()) { - saveInputStreamToFile(inputStream, fileDestination); - } - } - } - /** * Create a single InputStream. * The stream is constructed from the multiple provided file paths. @@ -367,13 +346,24 @@ private Dependency getDependencyLocally(ArtifactMetaData fileMetaData, String lo } protected ArtifactMetaData downloadArtifactMetaData(String url) throws IOException { - try (CloseableHttpResponse response = downloader.getClient().getArtifactMetadata(url)) { - EntityUtils.consumeQuietly(response.getEntity()); + try { ArtifactMetaData artifactMetaData = new ArtifactMetaData(); - artifactMetaData.setMd5(getHeaderContentFromResponse(response, MD5_HEADER_NAME)); - artifactMetaData.setSha1(getHeaderContentFromResponse(response, SHA1_HEADER_NAME)); - artifactMetaData.setSize(NumberUtils.toLong(getHeaderContentFromResponse(response, HttpHeaders.CONTENT_LENGTH))); - artifactMetaData.setAcceptRange("bytes".equals(getHeaderContentFromResponse(response, HttpHeaders.ACCEPT_RANGES))); + for (Header header : downloader.getArtifactoryManager().downloadHeaders(url)) { + switch (header.getName()) { + case MD5_HEADER_NAME: + artifactMetaData.setMd5(header.getValue()); + break; + case SHA1_HEADER_NAME: + artifactMetaData.setSha1(header.getValue()); + break; + case HttpHeaders.CONTENT_LENGTH: + artifactMetaData.setSize(NumberUtils.toLong(header.getValue())); + break; + case HttpHeaders.ACCEPT_RANGES: + artifactMetaData.setAcceptRange("bytes".equals(header.getValue())); + break; + } + } return artifactMetaData; } catch (NumberFormatException e) { throw new IOException(e); @@ -400,15 +390,6 @@ private String validateSha1Checksum(String metadataSha1, String calculatedSha1) return metadataSha1 == null ? "" : metadataSha1; } - private String getHeaderContentFromResponse(HttpResponse response, String headerName) { - String headerContent = null; - Header header = response.getFirstHeader(headerName); - if (header != null) { - headerContent = header.getValue(); - } - return headerContent; - } - private Dependency validateChecksumsAndBuildDependency(Map checksumsMap, ArtifactMetaData artifactMetaData, String filePath, String fileDestination, String remotePath) throws IOException { String md5 = validateMd5Checksum(artifactMetaData.getMd5(), checksumsMap.get(MD5_ALGORITHM_NAME)); diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderImpl.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderImpl.java index 835a77c97..e017904d1 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderImpl.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/DependenciesDownloaderImpl.java @@ -7,7 +7,7 @@ import org.jfrog.build.api.util.CommonUtils; import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.File; import java.io.IOException; @@ -25,21 +25,21 @@ */ public class DependenciesDownloaderImpl implements DependenciesDownloader { - private ArtifactoryDependenciesClient client; + private final ArtifactoryManager artifactoryManager; private File workingDirectory; private Log log; private boolean flatDownload = false; - public DependenciesDownloaderImpl(ArtifactoryDependenciesClient client, String workingDirectory, Log log) { + public DependenciesDownloaderImpl(ArtifactoryManager artifactoryManager, String workingDirectory, Log log) { this.workingDirectory = new File(workingDirectory); this.log = log; this.flatDownload = false; - this.client = client; + this.artifactoryManager = artifactoryManager; } @Override - public ArtifactoryDependenciesClient getClient() { - return client; + public ArtifactoryManager getArtifactoryManager() { + return artifactoryManager; } @Override diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/EditPropertiesHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/EditPropertiesHelper.java index 6dd997f14..81622630a 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/EditPropertiesHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/EditPropertiesHelper.java @@ -1,9 +1,8 @@ package org.jfrog.build.extractor.clientConfiguration.util; -import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.search.AqlSearchResult; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import org.jfrog.build.extractor.clientConfiguration.util.spec.Spec; @@ -16,18 +15,16 @@ public enum EditPropertiesActionType { DELETE } - private final ArtifactoryDependenciesClient client; + private final ArtifactoryManager artifactoryManager; private final Log log; - private final String artifactoryEditPropsUrl; - public EditPropertiesHelper(ArtifactoryDependenciesClient client, Log log) { - this.client = client; + public EditPropertiesHelper(ArtifactoryManager artifactoryManager, Log log) { + this.artifactoryManager = artifactoryManager; this.log = log; - this.artifactoryEditPropsUrl = StringUtils.stripEnd(client.getArtifactoryUrl(), "/") + "/api/storage/"; } public boolean editProperties(Spec spec, EditPropertiesActionType editType, String props) throws IOException { - ArtifactorySearcher searcher = new ArtifactorySearcher(client, log); + ArtifactorySearcher searcher = new ArtifactorySearcher(artifactoryManager, log); // Here to mark that at least one action has been successfully made. Needed for the failNoOp flag. boolean propertiesSet = false; @@ -46,11 +43,10 @@ public boolean editProperties(Spec spec, EditPropertiesActionType editType, Stri private boolean setPropertiesOnResults(List searchResults, String props) throws IOException { boolean propertiesSet = false; log.info("Setting properties..."); - validateSetProperties(props); for (AqlSearchResult.SearchEntry result : searchResults) { - String url = buildEntryUrl(result); - log.info(String.format("Setting the properties: '%s', on artifact: %s", props, url)); - client.setProperties(url, props); + String relativePath = buildEntryUrl(result); + log.info(String.format("Setting the properties: '%s', on artifact: %s", props, relativePath)); + artifactoryManager.setProperties(relativePath, props, true); propertiesSet = true; } log.info("Done setting properties."); @@ -61,9 +57,9 @@ private boolean deletePropertiesOnResults(List sear boolean propertiesSet = false; log.info("Deleting properties..."); for (AqlSearchResult.SearchEntry result : searchResults) { - String url = buildEntryUrl(result); - log.info(String.format("Deleting the properties: '%s', on artifact: %s", props, url)); - client.deleteProperties(url, props); + String relativePath = buildEntryUrl(result); + log.info(String.format("Deleting the properties: '%s', on artifact: %s", props, relativePath)); + artifactoryManager.deleteProperties(relativePath, props); propertiesSet = true; } log.info("Done deleting properties."); @@ -72,25 +68,6 @@ private boolean deletePropertiesOnResults(List sear private String buildEntryUrl(AqlSearchResult.SearchEntry result) { String path = result.getPath().equals(".") ? "" : result.getPath() + "/"; - return artifactoryEditPropsUrl + result.getRepo() + "/" + path + result.getName(); - } - - private void validateSetProperties(String props) throws IOException { - for (String prop : props.trim().split(";")) { - if (prop.isEmpty()) { - continue; - } - - String key = StringUtils.substringBefore(prop, "="); - if (key.isEmpty()) { - throw new IOException("Setting properties: Every property must have a key."); - } - - String values = StringUtils.substringAfter(prop, "="); - // Verify values aren't empty nor commas only - if (values.isEmpty() || StringUtils.countMatches(values, ",") == values.length()) { - throw new IOException("Setting properties: Every property must have at least one value."); - } - } + return result.getRepo() + "/" + path + result.getName(); } } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/JsonUtils.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/JsonUtils.java new file mode 100644 index 000000000..d25d977a8 --- /dev/null +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/JsonUtils.java @@ -0,0 +1,42 @@ +package org.jfrog.build.extractor.clientConfiguration.util; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +public class JsonUtils { + public static String toJsonString(Object object) throws IOException { + JsonFactory jsonFactory = createJsonFactory(); + StringWriter writer = new StringWriter(); + JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(writer); + jsonGenerator.useDefaultPrettyPrinter(); + jsonGenerator.writeObject(object); + return writer.getBuffer().toString(); + } + + public static JsonParser createJsonParser(InputStream in) throws IOException { + JsonFactory jsonFactory = createJsonFactory(); + return jsonFactory.createParser(in); + } + + public static JsonParser createJsonParser(String content) throws IOException { + JsonFactory jsonFactory = createJsonFactory(); + return jsonFactory.createParser(content); + } + + public static JsonFactory createJsonFactory() { + JsonFactory jsonFactory = new JsonFactory(); + ObjectMapper mapper = new ObjectMapper(jsonFactory); + mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector()); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + jsonFactory.setCodec(mapper); + return jsonFactory; + } +} diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/PatternAqlHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/PatternAqlHelper.java index 9ebd9e5ca..36ab2c38c 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/PatternAqlHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/PatternAqlHelper.java @@ -3,7 +3,7 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.util.spec.FileSpec; import java.io.IOException; @@ -12,7 +12,7 @@ import java.util.Objects; public class PatternAqlHelper extends AqlHelperBase { - PatternAqlHelper(ArtifactoryDependenciesClient client, Log log, FileSpec file) throws IOException { + PatternAqlHelper(ArtifactoryManager client, Log log, FileSpec file) throws IOException { super(client, log, file); } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/UrlUtils.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/UrlUtils.java index 4d604b527..368aac47e 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/UrlUtils.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/UrlUtils.java @@ -2,9 +2,13 @@ import org.apache.commons.lang.StringUtils; +import java.util.Iterator; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static org.jfrog.build.extractor.clientConfiguration.client.JFrogService.encodeUrl; + /** * Created by Bar Belity on 19/07/2020. */ @@ -28,4 +32,25 @@ public static String removeCredentialsFromUrl(String lineWithCredentials) { String protocol = matcher.group(1); return StringUtils.replace(lineWithCredentials, credentialsPart, protocol + "://"); } + + public static void appendParamsToUrl(Map requestParams, StringBuilder urlBuilder) { + if ((requestParams != null) && !requestParams.isEmpty()) { + urlBuilder.append("params="); + Iterator> paramEntryIterator = requestParams.entrySet().iterator(); + String encodedPipe = encodeUrl("|"); + while (paramEntryIterator.hasNext()) { + Map.Entry paramEntry = paramEntryIterator.next(); + urlBuilder.append(encodeUrl(paramEntry.getKey())); + String paramValue = paramEntry.getValue(); + if (StringUtils.isNotBlank(paramValue)) { + urlBuilder.append("=").append(encodeUrl(paramValue)); + } + + if (paramEntryIterator.hasNext()) { + + urlBuilder.append(encodedPipe); + } + } + } + } } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecDeploymentConsumer.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecDeploymentConsumer.java index 85dd817e3..545a8c46d 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecDeploymentConsumer.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecDeploymentConsumer.java @@ -2,7 +2,7 @@ import org.jfrog.build.api.producerConsumer.ProducerConsumerItem; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.producerConsumer.ConsumerRunnableBase; import org.jfrog.build.extractor.producerConsumer.ProducerConsumerExecutor; @@ -18,10 +18,10 @@ public class SpecDeploymentConsumer extends ConsumerRunnableBase { private ProducerConsumerExecutor executor; private Log log; - private ArtifactoryBuildInfoClient client; + private final ArtifactoryManager ArtifactoryManager; - public SpecDeploymentConsumer(ArtifactoryBuildInfoClient client) { - this.client = client; + public SpecDeploymentConsumer(ArtifactoryManager ArtifactoryManager) { + this.ArtifactoryManager = ArtifactoryManager; } @Override @@ -36,7 +36,7 @@ public void consumerRun() { break; } // Perform artifact deploy - client.deployArtifact((DeployDetails) item, "[" + Thread.currentThread().getName() + "]"); + ArtifactoryManager.upload((DeployDetails) item, "[" + Thread.currentThread().getName() + "]"); } catch (InterruptedException e) { return; } catch (IOException e) { diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelper.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelper.java index 058a19854..de26b99fc 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelper.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelper.java @@ -11,9 +11,8 @@ import org.jfrog.build.api.Dependency; import org.jfrog.build.api.builder.ArtifactBuilder; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.clientConfiguration.deploy.DeployDetails; import org.jfrog.build.extractor.clientConfiguration.util.DependenciesDownloaderHelper; import org.jfrog.build.extractor.clientConfiguration.util.EditPropertiesHelper; @@ -48,62 +47,62 @@ public SpecsHelper(Log log) { * Retains compatibility with other plugins using file specs * with default number of concurrent upload threads * - * @param uploadSpec The required spec represented as String - * @param workspace File object that represents the workspace - * @param buildProperties Upload properties - * @param clientBuilder ArtifactoryBuildInfoClientBuilder which will build the buildInfoClients to perform the actual upload + * @param uploadSpec The required spec represented as String + * @param workspace File object that represents the workspace + * @param buildProperties Upload properties + * @param artifactoryManagerBuilder ArtifactoryManagerBuilder which will build the ArtifactoryManager to perform the actual upload * @return Set of DeployDetails that was calculated from the given params * @throws IOException Thrown if any error occurs while reading the file, calculating the * checksums or in case of any file system exception */ public List uploadArtifactsBySpec(String uploadSpec, File workspace, Map buildProperties, - ArtifactoryBuildInfoClientBuilder clientBuilder) throws Exception { - return uploadArtifactsBySpec(uploadSpec, DEFAULT_NUMBER_OF_THREADS, workspace, createMultiMap(buildProperties), clientBuilder); + ArtifactoryManagerBuilder artifactoryManagerBuilder) throws Exception { + return uploadArtifactsBySpec(uploadSpec, DEFAULT_NUMBER_OF_THREADS, workspace, createMultiMap(buildProperties), artifactoryManagerBuilder); } /** * Upload artifacts according to a given spec, return a list describing the deployed items. * - * @param uploadSpec The required spec represented as String - * @param workspace File object that represents the workspace - * @param buildProperties Upload properties - * @param clientBuilder ArtifactoryBuildInfoClientBuilder which will build the buildInfoClients to perform the actual upload + * @param uploadSpec The required spec represented as String + * @param workspace File object that represents the workspace + * @param buildProperties Upload properties + * @param artifactoryManagerBuilder ArtifactoryManagerBuilder which will build the ArtifactoryManager to perform the actual upload * @return Set of DeployDetails that was calculated from the given params * @throws IOException Thrown if any error occurs while reading the file, calculating the * checksums or in case of any file system exception */ public List uploadArtifactsBySpec(String uploadSpec, File workspace, Multimap buildProperties, - ArtifactoryBuildInfoClientBuilder clientBuilder) throws Exception { - return uploadArtifactsBySpec(uploadSpec, DEFAULT_NUMBER_OF_THREADS, workspace, buildProperties, clientBuilder); + ArtifactoryManagerBuilder artifactoryManagerBuilder) throws Exception { + return uploadArtifactsBySpec(uploadSpec, DEFAULT_NUMBER_OF_THREADS, workspace, buildProperties, artifactoryManagerBuilder); } /** * Upload artifacts according to a given spec, return a list describing the deployed items. * - * @param uploadSpec The required spec represented as String - * @param numberOfThreads Number of concurrent threads to use for handling uploads - * @param workspace File object that represents the workspace - * @param buildProperties Upload properties - * @param clientBuilder ArtifactoryBuildInfoClientBuilder which will build the buildInfoClients per the number of passed threads number to perform the actual upload + * @param uploadSpec The required spec represented as String + * @param numberOfThreads Number of concurrent threads to use for handling uploads + * @param workspace File object that represents the workspace + * @param buildProperties Upload properties + * @param artifactoryManagerBuilder ArtifactoryManagerBuilder which will build the ArtifactoryManager per the number of passed threads number to perform the actual upload * @return Set of DeployDetails that was calculated from the given params * @throws IOException Thrown if any error occurs while reading the file, calculating the * checksums or in case of any file system exception */ public List uploadArtifactsBySpec(String uploadSpec, int numberOfThreads, File workspace, Multimap buildProperties, - ArtifactoryBuildInfoClientBuilder clientBuilder) throws Exception { + ArtifactoryManagerBuilder artifactoryManagerBuilder) throws Exception { Spec spec = this.getSpecFromString(uploadSpec, new UploadSpecValidator()); - try (ArtifactoryBuildInfoClient client = clientBuilder.build()) { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { // Create producer Runnable ProducerRunnableBase[] producerRunnable = new ProducerRunnableBase[]{new SpecDeploymentProducer(spec, workspace, buildProperties)}; // Create consumer Runnables ConsumerRunnableBase[] consumerRunnables = new ConsumerRunnableBase[numberOfThreads]; for (int i = 0; i < numberOfThreads; i++) { - consumerRunnables[i] = new SpecDeploymentConsumer(client); + consumerRunnables[i] = new SpecDeploymentConsumer(artifactoryManager); } // Create the deployment executor ProducerConsumerExecutor deploymentExecutor = new ProducerConsumerExecutor(log, producerRunnable, consumerRunnables, CONNECTION_POOL_SIZE); @@ -133,7 +132,7 @@ public static Multimap createMultiMap(Map input) { * @return A list of the downloaded dependencies. * @throws IOException in case of IOException */ - public List downloadArtifactsBySpec(String spec, ArtifactoryDependenciesClient client, String targetDirectory) throws IOException { + public List downloadArtifactsBySpec(String spec, ArtifactoryManager client, String targetDirectory) throws IOException { // During download, temp directories are created. This will make sure 'java.io.tmpdir' property is defined in Unix. handleJavaTmpdirProperty(); DependenciesDownloaderHelper helper = new DependenciesDownloaderHelper(client, targetDirectory, log); @@ -169,9 +168,9 @@ public Spec getSpecFromString(String specStr, SpecsValidator specsValidator) thr } @SuppressWarnings("unused") - public boolean editPropertiesBySpec(String spec, ArtifactoryDependenciesClient client, + public boolean editPropertiesBySpec(String spec, ArtifactoryManager artifactoryManager, EditPropertiesHelper.EditPropertiesActionType editType, String props) throws IOException { - EditPropertiesHelper helper = new EditPropertiesHelper(client, log); + EditPropertiesHelper helper = new EditPropertiesHelper(artifactoryManager, log); return helper.editProperties(getSpecFromString(spec, new SearchBasedSpecValidator()), editType, props); } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/issuesCollection/IssuesCollector.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/issuesCollection/IssuesCollector.java index 89c8c273a..86e84c6e6 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/issuesCollection/IssuesCollector.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/issuesCollection/IssuesCollector.java @@ -5,8 +5,8 @@ import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.*; import org.jfrog.build.api.util.Log; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.executor.CommandExecutor; import org.jfrog.build.extractor.executor.CommandResults; @@ -47,10 +47,10 @@ public static Pattern getRevisionNotExistPattern() { /** * Main function that manages the issue collection process. */ - public Issues collectIssues(File execDir, Log logger, String config, ArtifactoryBuildInfoClientBuilder clientBuilder, + public Issues collectIssues(File execDir, Log logger, String config, ArtifactoryManagerBuilder artifactoryManagerBuilder, String buildName, Vcs vcs, String project) throws InterruptedException, IOException { IssuesCollectionConfig parsedConfig = parseConfig(config); - String previousVcsRevision = getPreviousVcsRevision(clientBuilder, buildName, vcs, project); + String previousVcsRevision = getPreviousVcsRevision(artifactoryManagerBuilder, buildName, vcs, project); Set affectedIssues = doCollect(execDir, logger, parsedConfig, previousVcsRevision); return buildIssuesObject(parsedConfig, affectedIssues); } @@ -73,10 +73,10 @@ IssuesCollectionConfig parseConfig(String config) throws IOException { /** * Gets the previous vcs revision from the LATEST build published to Artifactory. */ - private String getPreviousVcsRevision(ArtifactoryBuildInfoClientBuilder clientBuilder, String prevBuildName, Vcs prevVcs, String project) throws IOException { - try (ArtifactoryBuildInfoClient client = clientBuilder.build()) { + private String getPreviousVcsRevision(ArtifactoryManagerBuilder artifactoryManagerBuilder, String prevBuildName, Vcs prevVcs, String project) throws IOException { + try (ArtifactoryManager artifactoryManager = artifactoryManagerBuilder.build()) { // Get LATEST build info from Artifactory - Build previousBuildInfo = client.getBuildInfo(prevBuildName, LATEST, project); + Build previousBuildInfo = artifactoryManager.getBuildInfo(prevBuildName, LATEST, project); if (previousBuildInfo == null) { return ""; } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/packageManager/PackageManagerExtractor.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/packageManager/PackageManagerExtractor.java index c39e1b2e1..fecac33d1 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/packageManager/PackageManagerExtractor.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/packageManager/PackageManagerExtractor.java @@ -4,7 +4,7 @@ import org.jfrog.build.api.Build; import org.jfrog.build.extractor.BuildInfoExtractorUtils; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBaseClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.File; import java.io.IOException; @@ -58,11 +58,11 @@ static void saveBuildInfoToFile(ArtifactoryClientConfiguration clientConfigurati } } - protected static void validateRepoExists(ArtifactoryBaseClient client, String repo, String repoNotSpecifiedMsg) throws IOException { + protected static void validateRepoExists(ArtifactoryManager client, String repo, String repoNotSpecifiedMsg) throws IOException { if (StringUtils.isBlank(repo)) { throw new IllegalArgumentException(repoNotSpecifiedMsg); } - if (!client.isRepoExist(repo)) { + if (!client.isRepositoryExist(repo)) { throw new IOException("Repo " + repo + " doesn't exist"); } } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/retention/Utils.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/retention/Utils.java index 8ead0db48..fd0e0d622 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/retention/Utils.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/retention/Utils.java @@ -3,16 +3,14 @@ import org.apache.commons.lang.StringUtils; import org.jfrog.build.api.Build; import org.jfrog.build.api.BuildRetention; -import org.jfrog.build.client.ArtifactoryHttpClient; import org.jfrog.build.client.ArtifactoryVersion; +import org.jfrog.build.client.JFrogHttpClient; import org.jfrog.build.extractor.clientConfiguration.ArtifactoryClientConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.util.VersionException; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.IOException; import java.util.Calendar; -import static org.jfrog.build.client.ArtifactoryHttpClient.encodeUrl; /** * Created by tamirh on 13/04/2017. @@ -42,43 +40,38 @@ private static BuildRetention getBuildRetention(ArtifactoryClientConfiguration c } private static void addRetentionIfNeeded(Build build, BuildRetention retention, ArtifactoryVersion version) { - if (!version.isAtLeast(ArtifactoryHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) { + if (!version.isAtLeast(JFrogHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) { build.setBuildRetention(retention); } } - private static void sendRetentionIfNeeded(ArtifactoryBuildInfoClient client, BuildRetention retention, String buildName, String project, ArtifactoryVersion version, boolean async) throws IOException { - if (version.isAtLeast(ArtifactoryHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) { - client.sendBuildRetetion(retention, encodeUrl(buildName), project, async); + private static void sendRetentionIfNeeded(ArtifactoryManager artifactoryManager, BuildRetention retention, String buildName, String project, ArtifactoryVersion version, boolean async) throws IOException { + if (version.isAtLeast(JFrogHttpClient.STANDALONE_BUILD_RETENTION_SUPPORTED_ARTIFACTORY_VERSION)) { + artifactoryManager.sendBuildRetention(retention, buildName, project, async); } } - public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, ArtifactoryClientConfiguration clientConf, String platformUrl) throws IOException { + public static void sendBuildAndBuildRetention(ArtifactoryManager artifactoryManager, Build build, ArtifactoryClientConfiguration clientConf, String platformUrl) throws IOException { BuildRetention retention = getBuildRetention(clientConf); - sendBuildAndBuildRetention(client, build, retention, clientConf.info.isAsyncBuildRetention(), platformUrl); + sendBuildAndBuildRetention(artifactoryManager, build, retention, clientConf.info.isAsyncBuildRetention(), platformUrl); } - public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, ArtifactoryClientConfiguration clientConfl) throws IOException { - sendBuildAndBuildRetention(client, build, clientConfl, null); + public static void sendBuildAndBuildRetention(ArtifactoryManager artifactoryManager, Build build, ArtifactoryClientConfiguration clientConfl) throws IOException { + sendBuildAndBuildRetention(artifactoryManager, build, clientConfl, null); } - public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, BuildRetention retention, boolean asyncBuildRetention, String platformUrl) throws IOException { + public static void sendBuildAndBuildRetention(ArtifactoryManager artifactoryManager, Build build, BuildRetention retention, boolean asyncBuildRetention, String platformUrl) throws IOException { if (retention == null || retention.isEmpty()) { - client.sendBuildInfo(build, platformUrl); + artifactoryManager.publishBuildInfo(build, platformUrl); return; } ArtifactoryVersion version; - try { - version = client.verifyCompatibleArtifactoryVersion(); - } catch (VersionException e) { - throw new RuntimeException(e); - } + version = artifactoryManager.getVersion(); addRetentionIfNeeded(build, retention, version); - client.sendBuildInfo(build, platformUrl); - sendRetentionIfNeeded(client, retention, build.getName(), build.getProject(), version, asyncBuildRetention); + artifactoryManager.publishBuildInfo(build, platformUrl); + sendRetentionIfNeeded(artifactoryManager, retention, build.getName(), build.getProject(), version, asyncBuildRetention); } - - public static void sendBuildAndBuildRetention(ArtifactoryBuildInfoClient client, Build build, BuildRetention retention, boolean asyncBuildRetention) throws IOException { - sendBuildAndBuildRetention(client, build, retention, asyncBuildRetention, null); + public static void sendBuildAndBuildRetention(ArtifactoryManager artifactoryManager, Build build, BuildRetention retention, boolean asyncBuildRetention) throws IOException { + sendBuildAndBuildRetention(artifactoryManager, build, retention, asyncBuildRetention, null); } } diff --git a/build-info-extractor/src/main/java/org/jfrog/build/extractor/usageReport/UsageReporter.java b/build-info-extractor/src/main/java/org/jfrog/build/extractor/usageReport/UsageReporter.java index cad2ccf1f..cf08d156d 100644 --- a/build-info-extractor/src/main/java/org/jfrog/build/extractor/usageReport/UsageReporter.java +++ b/build-info-extractor/src/main/java/org/jfrog/build/extractor/usageReport/UsageReporter.java @@ -2,7 +2,7 @@ import org.jfrog.build.api.util.Log; import org.jfrog.build.client.ProxyConfiguration; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import java.io.IOException; @@ -19,11 +19,11 @@ public UsageReporter(String productId, String[] featureIds) { } public void reportUsage(String artifactoryUrl, String username, String password, String accessToken, ProxyConfiguration proxyConfiguration, Log log) throws IOException { - ArtifactoryBuildInfoClient client = new ArtifactoryBuildInfoClient(artifactoryUrl, username, password, accessToken, log); + ArtifactoryManager artifactoryManager = new ArtifactoryManager(artifactoryUrl, username, password, accessToken, log); if (proxyConfiguration != null) { - client.setProxyConfiguration(proxyConfiguration); + artifactoryManager.setProxyConfiguration(proxyConfiguration); } - client.reportUsage(this); + artifactoryManager.reportUsage(this); } public String getProductId() { @@ -43,10 +43,10 @@ private void setFeatures(String[] featureIds) { } } - public class FeatureId { - private String featureId; + public static class FeatureId { + private final String featureId; - public FeatureId (String featureId) { + public FeatureId(String featureId) { this.featureId = featureId; } diff --git a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClientTest.java b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryManagerTest.java similarity index 87% rename from build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClientTest.java rename to build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryManagerTest.java index 915f09992..4e5cb3c3b 100644 --- a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryBuildInfoClientTest.java +++ b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/client/ArtifactoryManagerTest.java @@ -18,6 +18,8 @@ import java.util.Date; import java.util.List; +import static org.jfrog.build.extractor.clientConfiguration.util.JsonUtils.toJsonString; + /** * Integration tests for the ArtifactoryBuildInfoClient. * Performs tests using the infrastructure resources provided by IntegrationTestsBase (such as Artifactory, localRepo, and credentials). @@ -25,7 +27,7 @@ * @author Yahav Itzhak */ @Test -public class ArtifactoryBuildInfoClientTest extends IntegrationTestsBase { +public class ArtifactoryManagerTest extends IntegrationTestsBase { private static final String TEST_SPACE = "bi_client_test_space"; private static final File tempWorkspace = new File(System.getProperty("java.io.tmpdir"), TEST_SPACE); @@ -50,7 +52,7 @@ public void sendBuildInfoWithProjectTest() throws IOException { } private void doSendBuildInfoTest(String project) throws IOException { - final String BUILD_NAME = "ArtifactoryBuildInfoClientTest"; + final String BUILD_NAME = "ArtifactoryManagerTest"; final String BUILD_NUMBER = "13"; final Date STARTED = new Date(); final List VCS = Arrays.asList(new Vcs("foo", "1"), @@ -85,12 +87,12 @@ private void doSendBuildInfoTest(String project) throws IOException { Build buildInfoToSend = buildInfoBuilder.build(); // Publish build info - buildInfoClient.sendBuildInfo(buildInfoToSend, project); + artifactoryManager.publishBuildInfo(buildInfoToSend, project); // Get build info - Build receivedBuildInfo = buildInfoClient.getBuildInfo(BUILD_NAME, BUILD_NUMBER, project); + Build receivedBuildInfo = artifactoryManager.getBuildInfo(BUILD_NAME, BUILD_NUMBER, project); // Compare - Assert.assertEquals(buildInfoClient.toJsonString(buildInfoToSend), buildInfoClient.toJsonString(receivedBuildInfo)); + Assert.assertEquals(toJsonString(buildInfoToSend), toJsonString(receivedBuildInfo)); } } diff --git a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/DownloadTest.java b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/DownloadTest.java index b30f34277..2e88ccdfb 100644 --- a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/DownloadTest.java +++ b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/DownloadTest.java @@ -40,10 +40,10 @@ public class DownloadTest extends IntegrationTestsBase { @Test(dataProvider = "testDownloadFilesProvider") public void testBulkAndConcurrentDownload(Map uploadedChecksum, String fileName, long fileSize) throws Exception { - String uriWithParams = dependenciesClient.getArtifactoryUrl() + "/" + localRepo1 + "/" + TEST_REPO_PATH + "/" + fileName; + String uriWithParams = localRepo1 + "/" + TEST_REPO_PATH + "/" + fileName; String fileDestination = tempWorkspace.getPath() + File.separatorChar + "download" + File.separatorChar + fileName; - DependenciesDownloaderHelper helper = new DependenciesDownloaderHelper(dependenciesClient, tempWorkspace.getPath(), log); + DependenciesDownloaderHelper helper = new DependenciesDownloaderHelper(artifactoryManager, tempWorkspace.getPath(), log); DependenciesDownloaderHelper.ArtifactMetaData artifactMetaData = helper.downloadArtifactMetaData(uriWithParams); Assert.assertEquals(artifactMetaData.getSize(), fileSize); @@ -70,9 +70,9 @@ public void testBulkAndConcurrentDownload(Map uploadedChecksum, @Test(dataProvider = "testDownloadFilesProvider") public void testDownloadArtifact(Map uploadedChecksum, String fileName, long fileSize) throws Exception { - DependenciesDownloaderHelper dependenciesDownloaderHelper = new DependenciesDownloaderHelper(dependenciesClient, ".", log); + DependenciesDownloaderHelper dependenciesDownloaderHelper = new DependenciesDownloaderHelper(artifactoryManager, ".", log); - String repoUrl = dependenciesClient.getArtifactoryUrl() + "/" + localRepo1 + "/" + TEST_REPO_PATH; + String repoUrl = localRepo1 + "/" + TEST_REPO_PATH; String targetDirPath = tempWorkspace.getPath() + File.separatorChar + "download" + File.separatorChar; String url = repoUrl + "/" + fileName; @@ -92,9 +92,9 @@ public void testDownloadArtifact(Map uploadedChecksum, String fi @Test(dataProvider = "testDownloadFilesProvider") public void testDownloadArtifactWithoutContentLength(Map uploadedChecksum, String fileName, long fileSize) throws Exception { - DependenciesDownloaderHelper dependenciesDownloaderHelper = new DependenciesDownloaderHelper(dependenciesClient, ".", log); + DependenciesDownloaderHelper dependenciesDownloaderHelper = new DependenciesDownloaderHelper(artifactoryManager, ".", log); - String repoUrl = dependenciesClient.getArtifactoryUrl() + "/" + localRepo1 + "/" + TEST_REPO_PATH; + String repoUrl = localRepo1 + "/" + TEST_REPO_PATH; String targetDirPath = tempWorkspace.getPath() + File.separatorChar + "download" + File.separatorChar; String url = repoUrl + "/" + fileName; @@ -118,7 +118,7 @@ public void testDownloadArtifactWithoutContentLength(Map uploade */ @DataProvider private Object[][] testDownloadFilesProvider() throws IOException, NoSuchAlgorithmException { - if (buildInfoClient == null) { + if (artifactoryManager == null) { throw new IOException("tests were not initialized successfully. aborting"); } Map testFilesMap = new HashMap() {{ @@ -149,7 +149,7 @@ private Object[][] testDownloadFilesProvider() throws IOException, NoSuchAlgorit .build(); // Upload artifact - buildInfoClient.deployArtifact(deployDetails); + artifactoryManager.upload(deployDetails); long createdFileSize = deployDetails.getFile().length(); tests[i] = new Object[]{checksum, fileName, createdFileSize}; diff --git a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/PropertiesTest.java b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/PropertiesTest.java index 7bf05509a..1293b68ac 100644 --- a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/PropertiesTest.java +++ b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/PropertiesTest.java @@ -48,7 +48,7 @@ public void propsTest() throws Exception { // Upload artifacts. String uploadSpec = readSpec(new File(propsTestPath, UPLOAD_SPEC), tempWorkspace.getPath()); File uploadFromPath = new File(this.getClass().getResource("/workspace").toURI()).getCanonicalFile(); - List uploaded = specsHelper.uploadArtifactsBySpec(uploadSpec, uploadFromPath, new HashMap<>(), buildInfoClientBuilder); + List uploaded = specsHelper.uploadArtifactsBySpec(uploadSpec, uploadFromPath, new HashMap<>(), artifactoryManagerBuilder); Reporter.log("Uploaded " + uploaded.size() + " artifacts", true); // Edit properties on the uploaded artifacts and verify. @@ -61,10 +61,10 @@ private void editPropsAndVerify(String specPath, EditPropertiesHelper.EditProper Expected expected = mapper.readValue(new File(propsTestPath, expectedPath), Expected.class); // Edit Properties on the uploaded artifacts - specsHelper.editPropertiesBySpec(spec, dependenciesClient, editType, props); + specsHelper.editPropertiesBySpec(spec, artifactoryManager, editType, props); - // Download artifacts to compare against the expected result. - List downloaded = specsHelper.downloadArtifactsBySpec(downloadSpec, dependenciesClient, tempWorkspace.getPath()); + // DownloadBase artifacts to compare against the expected result. + List downloaded = specsHelper.downloadArtifactsBySpec(downloadSpec, artifactoryManager, tempWorkspace.getPath()); Reporter.log("Downloaded " + downloaded.size() + " artifacts", true); // Verify expected results diff --git a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelperIntegrationTest.java b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelperIntegrationTest.java index 0893f3378..4177039f6 100644 --- a/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelperIntegrationTest.java +++ b/build-info-extractor/src/test/java/org/jfrog/build/extractor/clientConfiguration/util/spec/SpecsHelperIntegrationTest.java @@ -34,14 +34,14 @@ public class SpecsHelperIntegrationTest extends IntegrationTestsBase { @BeforeClass public void init() throws IOException { super.init(); - if (!dependenciesClient.isArtifactoryOSS()) { + if (!artifactoryManager.getVersion().isOSS()) { createTestRepo(localRepo2); } } @AfterClass protected void terminate() throws IOException { - if (!dependenciesClient.isArtifactoryOSS()) { + if (!artifactoryManager.getVersion().isOSS()) { deleteTestRepo(localRepo2); } super.terminate(); @@ -61,11 +61,11 @@ public void integrationTests(SingleSpecTest specTest) throws Exception { // Upload artifacts. File uploadFromPath = new File(this.getClass().getResource("/workspace").toURI()).getCanonicalFile(); - List uploaded = specsHelper.uploadArtifactsBySpec(specTest.uploadSpec, uploadFromPath, new HashMap<>(), buildInfoClientBuilder); + List uploaded = specsHelper.uploadArtifactsBySpec(specTest.uploadSpec, uploadFromPath, new HashMap<>(), artifactoryManagerBuilder); Reporter.log("Uploaded " + uploaded.size() + " artifacts", false); // Download artifacts to compare against the expected result. - List downloaded = specsHelper.downloadArtifactsBySpec(specTest.downloadSpec, dependenciesClient, tempWorkspace.getPath()); + List downloaded = specsHelper.downloadArtifactsBySpec(specTest.downloadSpec, artifactoryManager, tempWorkspace.getPath()); Reporter.log("Downloaded " + downloaded.size() + " artifacts", false); // Verify expected results diff --git a/build-info-extractor/src/test/java/org/jfrog/build/extractor/issuesCollection/IssuesCollectorTest.java b/build-info-extractor/src/test/java/org/jfrog/build/extractor/issuesCollection/IssuesCollectorTest.java index dc7f47d11..bd5d38dee 100644 --- a/build-info-extractor/src/test/java/org/jfrog/build/extractor/issuesCollection/IssuesCollectorTest.java +++ b/build-info-extractor/src/test/java/org/jfrog/build/extractor/issuesCollection/IssuesCollectorTest.java @@ -113,7 +113,7 @@ private void runCollectIssues(String sourceFolder, List vcs, int expectedNu // Get config String successfulConfig = FileUtils.readFileToString(new File(testResourcesPath, "issues_config_full_test.json"), "UTF-8"); - Issues issues = collector.collectIssues(dotGitPath, getLog(), successfulConfig, buildInfoClientBuilder, BUILD_NAME, vcs.get(0), null); + Issues issues = collector.collectIssues(dotGitPath, getLog(), successfulConfig, artifactoryManagerBuilder, BUILD_NAME, vcs.get(0), null); Assert.assertNotNull(issues); Assert.assertNotNull(issues.getAffectedIssues()); @@ -129,7 +129,7 @@ private void publishBuildInfoWithVcs(List vcsList) throws IOException { Build buildInfoToSend = buildInfoBuilder.build(); // Publish build info - buildInfoClient.sendBuildInfo(buildInfoToSend, null); + artifactoryManager.publishBuildInfo(buildInfoToSend, null); } @BeforeMethod diff --git a/build-info-extractor/src/testFixtures/java/org/jfrog/build/IntegrationTestsBase.java b/build-info-extractor/src/testFixtures/java/org/jfrog/build/IntegrationTestsBase.java index a935794d6..f9cdcd710 100644 --- a/build-info-extractor/src/testFixtures/java/org/jfrog/build/IntegrationTestsBase.java +++ b/build-info-extractor/src/testFixtures/java/org/jfrog/build/IntegrationTestsBase.java @@ -1,26 +1,17 @@ package org.jfrog.build; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.*; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.InputStreamEntity; -import org.apache.http.util.EntityUtils; import org.jfrog.build.api.util.Log; -import org.jfrog.build.client.ArtifactoryHttpClient; -import org.jfrog.build.client.PreemptiveHttpClient; -import org.jfrog.build.extractor.clientConfiguration.ArtifactoryBuildInfoClientBuilder; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; -import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryDependenciesClient; +import org.jfrog.build.extractor.clientConfiguration.ArtifactoryManagerBuilder; +import org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager; import org.jfrog.build.extractor.util.TestingLog; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -36,21 +27,7 @@ */ public abstract class IntegrationTestsBase { - private String username; - private String password; - private String url; - protected String localRepo1 = "build-info-tests-local"; - protected String localRepo2 = "build-info-tests-local2"; - protected String remoteRepo; - protected String virtualRepo = "build-info-tests-virtual"; - protected String localRepositoriesWildcard = "build-info-tests-local*"; - protected ArtifactoryBuildInfoClient buildInfoClient; - protected ArtifactoryBuildInfoClientBuilder buildInfoClientBuilder; - protected ArtifactoryDependenciesClient dependenciesClient; protected static final Log log = new TestingLog(); - - private PreemptiveHttpClient preemptiveHttpClient; - protected static final String LOCAL_REPO_PLACEHOLDER = "${LOCAL_REPO}"; protected static final String LOCAL_REPO2_PLACEHOLDER = "${LOCAL_REPO2}"; protected static final String VIRTUAL_REPO_PLACEHOLDER = "${VIRTUAL_REPO}"; @@ -59,10 +36,22 @@ public abstract class IntegrationTestsBase { protected static final String UPLOAD_SPEC = "upload.json"; protected static final String DOWNLOAD_SPEC = "download.json"; protected static final String EXPECTED = "expected.json"; - protected static final String BITESTS_ARTIFACTORY_ENV_VAR_PREFIX = "BITESTS_ARTIFACTORY_"; private static final String BITESTS_ARTIFACTORY_PROPERTIES_PREFIX = "bitests.artifactory."; - private static final String API_REPOSITORIES = "api/repositories"; + protected String localRepo1 = "build-info-tests-local"; + protected String localRepo2 = "build-info-tests-local2"; + protected String remoteRepo; + protected String virtualRepo = "build-info-tests-virtual"; + protected String localRepositoriesWildcard = "build-info-tests-local*"; + protected ArtifactoryManager artifactoryManager; + protected ArtifactoryManagerBuilder artifactoryManagerBuilder; + private String username; + private String password; + private String url; + + public static Log getLog() { + return log; + } @BeforeClass public void init() throws IOException { @@ -81,29 +70,37 @@ public void init() throws IOException { } username = readParam(props, "username"); password = readParam(props, "password"); - preemptiveHttpClient = createHttpClient().getHttpClient(); - buildInfoClient = createBuildInfoClient(); - buildInfoClientBuilder = createBuildInfoClientBuilder(); - dependenciesClient = createDependenciesClient(); + artifactoryManager = createArtifactoryManager(); + artifactoryManagerBuilder = createArtifactoryManagerBuilder(); - if (!dependenciesClient.isArtifactoryOSS()) { - createTestRepo(localRepo1); - createTestRepo(remoteRepo); - createTestRepo(virtualRepo); + if (!artifactoryManager.getVersion().isOSS()) { + if (StringUtils.isNotEmpty(localRepo1)) { + createTestRepo(localRepo1); + } + if (StringUtils.isNotEmpty(remoteRepo)) { + createTestRepo(remoteRepo); + } + if (StringUtils.isNotEmpty(virtualRepo)) { + createTestRepo(virtualRepo); + } } } @AfterClass protected void terminate() throws IOException { - if (!dependenciesClient.isArtifactoryOSS()) { + if (!artifactoryManager.getVersion().isOSS()) { // Delete the virtual first. - deleteTestRepo(virtualRepo); - deleteTestRepo(remoteRepo); - deleteTestRepo(localRepo1); + if (StringUtils.isNotEmpty(virtualRepo)) { + deleteTestRepo(virtualRepo); + } + if (StringUtils.isNotEmpty(remoteRepo)) { + deleteTestRepo(remoteRepo); + } + if (StringUtils.isNotEmpty(localRepo1)) { + deleteTestRepo(localRepo1); + } } - preemptiveHttpClient.close(); - buildInfoClient.close(); - dependenciesClient.close(); + artifactoryManager.close(); } private String readParam(Properties props, String paramName) { @@ -141,65 +138,40 @@ private void failInit() { * Delete all content from the given repository. * * @param repo - repository name - * @throws IOException */ protected void deleteContentFromRepo(String repo) throws IOException { if (!isRepoExists(repo)) { return; } - String fullItemUrl = url + repo + "/"; - String itemUrl = ArtifactoryHttpClient.encodeUrl(fullItemUrl); - HttpRequestBase httpRequest = new HttpDelete(itemUrl); - - try (CloseableHttpResponse response = preemptiveHttpClient.execute(httpRequest)) { - EntityUtils.consumeQuietly(response.getEntity()); - StatusLine statusLine = response.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - if (statusCode == HttpStatus.SC_UNAUTHORIZED) { - throw new FileNotFoundException("Bad credentials for username: " + username); - } - if (statusCode < 200 || statusCode >= 300) { - throw new IOException(getRepositoryCustomErrorMessage(repo, false, statusLine)); - } - } + artifactoryManager.deleteRepositoryContent(repo); } /** * Check if repository exists. * * @param repo - repository name - * @return - * @throws IOException */ private boolean isRepoExists(String repo) throws IOException { - HttpRequestBase httpRequest = new HttpGet(getRepoApiUrl(repo)); - try (CloseableHttpResponse response = preemptiveHttpClient.execute(httpRequest)) { - EntityUtils.consumeQuietly(response.getEntity()); - return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK; - } + return artifactoryManager.isRepositoryExist(repo); } /** * Create new repository according to the settings. * * @param repo - repository name - * @throws IOException + * @throws IOException in case of any connection issues with Artifactory or the repository doesn't exist. */ protected void createTestRepo(String repo) throws IOException { if (StringUtils.isBlank(repo) || isRepoExists(repo)) { return; } - HttpPut httpRequest = new HttpPut(getRepoApiUrl(repo)); - try (InputStream repoConfigInputStream = this.getClass().getResourceAsStream("/integration/settings/" + repo + ".json")) { - InputStreamEntity repoConfigEntity = new InputStreamEntity(repoConfigInputStream, ContentType.create("application/json")); - httpRequest.setEntity(repoConfigEntity); - try (CloseableHttpResponse response = preemptiveHttpClient.execute(httpRequest)) { - EntityUtils.consumeQuietly(response.getEntity()); - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_CREATED) { - throw new IOException(getRepositoryCustomErrorMessage(repo, true, response.getStatusLine())); - } + String path = "/integration/settings/" + repo + ".json"; + try (InputStream repoConfigInputStream = this.getClass().getResourceAsStream(path)) { + if (repoConfigInputStream == null) { + throw new IOException("Couldn't find repository settings in " + path); } + String json = IOUtils.toString(repoConfigInputStream, StandardCharsets.UTF_8); + artifactoryManager.createRepository(repo, json); } } @@ -210,30 +182,16 @@ protected void createTestRepo(String repo) throws IOException { * @throws IOException */ protected void deleteTestRepo(String repo) throws IOException { - if (StringUtils.isBlank(repo)) { - return; - } - HttpRequestBase httpRequest = new HttpDelete(getRepoApiUrl(repo)); - try (CloseableHttpResponse response = preemptiveHttpClient.execute(httpRequest)) { - EntityUtils.consumeQuietly(response.getEntity()); - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - throw new IOException(getRepositoryCustomErrorMessage(repo, false, response.getStatusLine())); - } - } - } - - private String getRepoApiUrl(String repo) { - String fullItemUrl = url + StringUtils.join(new String[]{API_REPOSITORIES, repo}, "/"); - return ArtifactoryHttpClient.encodeUrl(fullItemUrl); + artifactoryManager.deleteRepository(repo); } /** * Read spec file and replace the placeholder test data. * - * @param specFile - * @return - * @throws IOException + * @param specFile - the spec file + * @param workSpacePath - workspace path + * @return the File Spec as a string. + * @throws IOException in case of any I/O error. */ protected String readSpec(File specFile, String workSpacePath) throws IOException { String spec = FileUtils.readFileToString(specFile, StandardCharsets.UTF_8); @@ -273,27 +231,15 @@ protected String getUrl() { return this.url; } - public static Log getLog() { - return log; + private ArtifactoryManager createArtifactoryManager() { + return new ArtifactoryManager(url, username, password, log); } - private ArtifactoryBuildInfoClient createBuildInfoClient() { - return new ArtifactoryBuildInfoClient(url, username, password, log); - } - - private ArtifactoryBuildInfoClientBuilder createBuildInfoClientBuilder() { - ArtifactoryBuildInfoClientBuilder builder = new ArtifactoryBuildInfoClientBuilder(); + private ArtifactoryManagerBuilder createArtifactoryManagerBuilder() { + ArtifactoryManagerBuilder builder = new ArtifactoryManagerBuilder(); return builder.setArtifactoryUrl(url).setUsername(username).setPassword(password).setLog(log); } - private ArtifactoryDependenciesClient createDependenciesClient() { - return new ArtifactoryDependenciesClient(url, username, password, StringUtils.EMPTY, log); - } - - private ArtifactoryHttpClient createHttpClient() { - return new ArtifactoryHttpClient(url, username, password, log); - } - /** * Expected inner class for testing purposes. * Contains the local files expected to be found after successful download. @@ -309,24 +255,4 @@ public void setFiles(List files) { this.files = files; } } - - /*** - * Returns a custom exception error to be thrown when repository creation/deletion fails. - * @param repo - repo name. - * @param creating - creation or deletion failed. - * @param statusLine - status returned. - * @return - custom error message. - */ - private String getRepositoryCustomErrorMessage(String repo, boolean creating, StatusLine statusLine) { - StringBuilder builder = new StringBuilder() - .append("Error ") - .append(creating ? "creating" : "deleting") - .append(" '").append(repo).append("'. ") - .append("Code: ").append(statusLine.getStatusCode()); - if (statusLine.getReasonPhrase() != null) { - builder.append(" Message: ") - .append(statusLine.getReasonPhrase()); - } - return builder.toString(); - } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index d0372edad..069136fb6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -build-info-version=2.26.1 -build-info-extractor-gradle-version=4.24.1 +build-info-version=2.26.x-SNAPSHOT +build-info-extractor-gradle-version=4.24.x-SNAPSHOT