Skip to content
Browse files

Merge branch 'master' of github.com:JFrogDev/build-info

  • Loading branch information...
2 parents 9654ba0 + 379ce6a commit b402c2c3c0cdece7db08558cd9510110e99bf2ff noamt committed Apr 20, 2012
View
57 build-info-api/src/main/java/org/jfrog/build/api/dependency/DownloadableArtifact.java
@@ -0,0 +1,57 @@
+package org.jfrog.build.api.dependency;
+
+import java.io.Serializable;
+
+/**
+ * Represents an artifact to be downloaded, used by generic resolving.
+ *
+ * @author Shay Yaakov
+ */
+public class DownloadableArtifact implements Serializable {
+ String repoUrl;
+ String relativeDirPath;
+ String filePath;
+ String matrixParameters;
+
+ public DownloadableArtifact() {
+ }
+
+ public DownloadableArtifact(String repoUrl, String relativeDirPath, String filePath, String matrixParameters) {
+ this.repoUrl = repoUrl;
+ this.relativeDirPath = relativeDirPath;
+ this.filePath = filePath;
+ this.matrixParameters = matrixParameters;
+ }
+
+ public String getRepoUrl() {
+ return repoUrl;
+ }
+
+ public void setRepoUrl(String repoUrl) {
+ this.repoUrl = repoUrl;
+ }
+
+ public String getRelativeDirPath() {
+ return relativeDirPath;
+ }
+
+ public void setRelativeDirPath(String relativeDirPath) {
+ this.relativeDirPath = relativeDirPath;
+ }
+
+ public String getFilePath() {
+ return filePath;
+ }
+
+ public void setFilePath(String filePath) {
+ this.filePath = filePath;
+ }
+
+ public String getMatrixParameters() {
+ return matrixParameters;
+ }
+
+ public void setMatrixParameters(String matrixParameters) {
+ this.matrixParameters = matrixParameters;
+ }
+}
View
77 build-info-api/src/main/java/org/jfrog/build/api/dependency/PatternResultFileSet.java
@@ -0,0 +1,77 @@
+/*
+ * 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.api.dependency;
+
+import com.google.common.collect.Sets;
+
+import java.util.Set;
+
+/**
+ * @author Noam Y. Tenne
+ */
+public class PatternResultFileSet {
+
+ private String repoUri;
+ private String sourcePattern;
+ private Set<String> files = Sets.newHashSet();
+
+ public PatternResultFileSet() {
+ }
+
+ public PatternResultFileSet(String repoUri, String sourcePattern) {
+ this.repoUri = repoUri;
+ this.sourcePattern = sourcePattern;
+ }
+
+ public PatternResultFileSet(String repoUri, String sourcePattern, Set<String> files) {
+ this.repoUri = repoUri;
+ this.sourcePattern = sourcePattern;
+ this.files = files;
+ }
+
+ public String getRepoUri() {
+ return repoUri;
+ }
+
+ public void setRepoUri(String repoUri) {
+ this.repoUri = repoUri;
+ }
+
+ public String getSourcePattern() {
+ return sourcePattern;
+ }
+
+ public void setSourcePattern(String sourcePattern) {
+ this.sourcePattern = sourcePattern;
+ }
+
+ public Set<String> getFiles() {
+ return files;
+ }
+
+ public void setFiles(Set<String> files) {
+ this.files = files;
+ }
+
+ public void addFile(String fileRelativePath) {
+ if (files == null) {
+ files = Sets.newHashSet();
+ }
+
+ files.add(fileRelativePath);
+ }
+}
View
158 build-info-api/src/main/java/org/jfrog/build/api/dependency/UserBuildDependency.java
@@ -0,0 +1,158 @@
+package org.jfrog.build.api.dependency;
+
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * Build dependency, as converted from user input like
+ * "libs-release-local:com/goldin/plugins/gradle/0.1.1/*.jar;status+=prod@gradle-plugins :: Build :: Gradle#LATEST => many-jars-build"
+ */
+public class UserBuildDependency {
+ private final String buildName; // "gradle-plugins :: Build :: Gradle"
+ private final String buildNumberRequest; // "LATEST"
+ private final List<Pattern> patterns = Lists.newLinkedList(); // "libs-release-local:com/plugins/gradle/0.1.1/*.jar;status+=prod"
+ private String buildNumberResponse; // "5"
+ private String buildStarted; //
+ private String buildUrl; //
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ UserBuildDependency that = (UserBuildDependency) o;
+
+ return !(buildName != null ? !buildName.equals(that.buildName) : that.buildName != null) && !(
+ buildNumberResponse != null ? !buildNumberResponse.equals(that.buildNumberResponse) :
+ that.buildNumberResponse != null) && !(buildStarted != null ?
+ !buildStarted.equals(that.buildStarted) : that.buildStarted != null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = buildName != null ? buildName.hashCode() : 0;
+ result = 31 * result + (buildNumberResponse != null ? buildNumberResponse.hashCode() : 0);
+ result = 31 * result + (buildStarted != null ? buildStarted.hashCode() : 0);
+ return result;
+ }
+
+ public static class Pattern {
+
+ private final String artifactoryPattern; // "libs-release-local:com/plugins/gradle/0.1.1/*.jar"
+ private final String matrixParameters; // "status+=prod"
+ private final String targetDirectory; // Directory to download dependencies to
+ private PatternResult patternResult; // Pattern result as received from Artifactory
+
+ public Pattern(String artifactoryPattern, String matrixParameters, String targetDirectory) {
+
+ if (StringUtils.isBlank(artifactoryPattern)) {
+ throw new IllegalArgumentException("Artifactory pattern is blank");
+ }
+ if (matrixParameters == null) {
+ throw new NullPointerException("Matrix parameters is null");
+ } // Can be empty.
+ if (targetDirectory == null) {
+ throw new NullPointerException("Target directory is null");
+ } // Can be empty.
+
+ this.artifactoryPattern = artifactoryPattern;
+ this.matrixParameters = matrixParameters;
+ this.targetDirectory = targetDirectory;
+ }
+
+ public String getArtifactoryPattern() {
+ return this.artifactoryPattern;
+ }
+
+ public String getMatrixParameters() {
+ return this.matrixParameters;
+ }
+
+ public String getTargetDirectory() {
+ return this.targetDirectory;
+ }
+
+ public PatternResult getPatternResult() {
+ return this.patternResult;
+ }
+
+ public void setPatternResult(PatternResult patternResult) {
+ this.patternResult = patternResult;
+ }
+ }
+
+
+ public UserBuildDependency(String buildName, String buildNumberRequest, String pattern, String targetDirectory) {
+
+ if (StringUtils.isBlank(buildName)) {
+ throw new IllegalArgumentException("Build name is blank");
+ }
+ if (StringUtils.isBlank(buildNumberRequest)) {
+ throw new IllegalArgumentException("Build number is blank");
+ }
+
+ this.buildName = buildName;
+ this.buildNumberRequest = buildNumberRequest;
+ addPattern(pattern, targetDirectory);
+ }
+
+
+ public String getBuildName() {
+ return this.buildName;
+ }
+
+ public String getBuildNumberRequest() {
+ return this.buildNumberRequest;
+ }
+
+ public List<Pattern> getPatterns() {
+ return Collections.unmodifiableList(this.patterns);
+ }
+
+ public String getBuildNumberResponse() {
+ return this.buildNumberResponse;
+ }
+
+ public void setBuildNumberResponse(String buildNumberResponse) {
+ this.buildNumberResponse = buildNumberResponse;
+ }
+
+ public String getBuildStarted() {
+ return this.buildStarted;
+ }
+
+ public void setBuildStarted(String buildStarted) {
+ this.buildStarted = buildStarted;
+ }
+
+ public String getBuildUrl() {
+ return this.buildUrl;
+ }
+
+ public void setBuildUrl(String buildUrl) {
+ this.buildUrl = buildUrl;
+ }
+
+
+ public void addPattern(String pattern, String targetDirectory) {
+ if (StringUtils.isBlank(pattern)) {
+ throw new IllegalArgumentException("Pattern can not be blank!");
+ }
+
+ int j = pattern.lastIndexOf(';');
+ Pattern p = new Pattern((j > 0) ? pattern.substring(0, j) : pattern,
+ (j > 0) ? pattern.substring(j + 1) : "",
+ targetDirectory);
+ this.patterns.add(p);
+ }
+}
View
63 build-info-api/src/test/java/org/jfrog/build/api/dependency/PatternResultFileSetTest.java
@@ -0,0 +1,63 @@
+package org.jfrog.build.api.dependency;
+
+import com.google.common.collect.Sets;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+import static org.testng.Assert.*;
+
+/**
+ * @author Noam Y. Tenne
+ */
+@Test
+public class PatternResultFileSetTest {
+
+ public void testInitDefaultConstructor() {
+ PatternResultFileSet fileSet = new PatternResultFileSet();
+ assertNull(fileSet.getRepoUri(), "Default repo URI should be null.");
+ assertNull(fileSet.getSourcePattern(), "Default source pattern should be null.");
+ assertNotNull(fileSet.getFiles(), "Default file set should not be null.");
+ assertTrue(fileSet.getFiles().isEmpty(), "Default file set should be empty.");
+ }
+
+ public void testInitNoFileSetConstructor() {
+ PatternResultFileSet fileSet = new PatternResultFileSet("repoUri", "sourcePattern");
+ assertEquals(fileSet.getRepoUri(), "repoUri", "Unexpected repo URI.");
+ assertEquals(fileSet.getSourcePattern(), "sourcePattern", "Unexpected source pattern.");
+ assertNotNull(fileSet.getFiles(), "Default file set should not be null.");
+ assertTrue(fileSet.getFiles().isEmpty(), "Default file set should be empty.");
+ }
+
+ public void testInitFullConstructor() {
+ Set<String> files = Sets.newHashSet("bob");
+
+ PatternResultFileSet fileSet = new PatternResultFileSet("repoUri", "sourcePattern", files);
+ assertEquals(fileSet.getRepoUri(), "repoUri", "Unexpected repo URI.");
+ assertEquals(fileSet.getSourcePattern(), "sourcePattern", "Unexpected source pattern.");
+ assertEquals(files, fileSet.getFiles(), "Unexpected file set.");
+ }
+
+ public void testSetterMethods() {
+ Set<String> files = Sets.newHashSet("bob");
+
+ PatternResultFileSet fileSet = new PatternResultFileSet();
+ fileSet.setRepoUri("repoUri");
+ fileSet.setSourcePattern("sourcePattern");
+ fileSet.setFiles(files);
+
+ assertEquals(fileSet.getRepoUri(), "repoUri", "Unexpected repo URI.");
+ assertEquals(fileSet.getSourcePattern(), "sourcePattern", "Unexpected source pattern.");
+ assertEquals(files, fileSet.getFiles(), "Unexpected file set.");
+ }
+
+ public void testAdderMethods() {
+ PatternResultFileSet fileSet = new PatternResultFileSet(null, null, null);
+ fileSet.addFile("moo");
+
+ assertNotNull(fileSet.getFiles(), "File set should not be null.");
+ assertFalse(fileSet.getFiles().isEmpty(), "File set should not be empty.");
+ assertEquals(fileSet.getFiles().size(), 1, "Unexpected file set size.");
+ assertEquals(fileSet.getFiles().iterator().next(), "moo", "Unexpected file set content.");
+ }
+}
View
37 build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryBuildInfoClient.java
@@ -500,15 +500,13 @@ private void uploadFile(DeployDetails details, String uploadUrl) throws IOExcept
if (tryChecksumDeploy(details, uploadUrl)) {
return;
}
- StringBuilder deploymentPathBuilder = new StringBuilder().append(uploadUrl);
- deploymentPathBuilder.append(buildMatrixParamsString(details.properties));
- HttpPut httpPut = new HttpPut(deploymentPathBuilder.toString());
- httpPut.addHeader("X-Checksum-Sha1", details.sha1);
- httpPut.addHeader("X-Checksum-Md5", details.md5);
+
+ HttpPut httpPut = createHttpPutMethod(details, uploadUrl);
// add the 100 continue directive
httpPut.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
FileEntity fileEntity = new FileEntity(details.file, "binary/octet-stream");
+
StatusLine statusLine = httpClient.upload(httpPut, fileEntity);
int statusCode = statusLine.getStatusCode();
@@ -518,7 +516,7 @@ private void uploadFile(DeployDetails details, String uploadUrl) throws IOExcept
}
}
- private boolean tryChecksumDeploy(DeployDetails details, String uploadUrl) {
+ private boolean tryChecksumDeploy(DeployDetails details, String uploadUrl) throws UnsupportedEncodingException {
// Try checksum deploy only on file size greater than CHECKSUM_DEPLOY_MIN_FILE_SIZE
long fileLength = details.file.length();
if (fileLength < CHECKSUM_DEPLOY_MIN_FILE_SIZE) {
@@ -528,36 +526,41 @@ private boolean tryChecksumDeploy(DeployDetails details, String uploadUrl) {
// 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"))) {
- log.info("Artifactory version is:" + getArtifactoryVersion());
return false;
}
- String fileAbsolutePath = details.file.getAbsolutePath();
- String sha1 = details.sha1;
- HttpPut httpPut = new HttpPut(uploadUrl);
+ HttpPut httpPut = createHttpPutMethod(details, uploadUrl);
+ // activate checksum deploy
httpPut.addHeader("X-Checksum-Deploy", "true");
- httpPut.addHeader("X-Checksum-Sha1", sha1);
- log.info(sha1);
- // add the 100 continue directive
- httpPut.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
+
+ String fileAbsolutePath = details.file.getAbsolutePath();
try {
StatusLine statusLine = httpClient.execute(httpPut);
int statusCode = statusLine.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 + " : " + sha1);
+ log.debug("Successfully performed checksum deploy of file " + fileAbsolutePath + " : " + details.sha1);
return true;
} else {
- log.debug("Failed checksum deploy of checksum '" + sha1 + "' with statusCode: " + statusCode);
+ log.debug("Failed checksum deploy of checksum '" + details.sha1 + "' with statusCode: " + statusCode);
}
} catch (IOException e) {
- log.debug("Failed trying artifact checksum deploy of file " + fileAbsolutePath + " : " + sha1);
+ log.debug("Failed artifact checksum deploy of file " + fileAbsolutePath + " : " + details.sha1);
}
return false;
}
+ private HttpPut createHttpPutMethod(DeployDetails details, String uploadUrl) throws UnsupportedEncodingException {
+ StringBuilder deploymentPathBuilder = new StringBuilder().append(uploadUrl);
+ deploymentPathBuilder.append(buildMatrixParamsString(details.properties));
+ HttpPut httpPut = new HttpPut(deploymentPathBuilder.toString());
+ httpPut.addHeader("X-Checksum-Sha1", details.sha1);
+ httpPut.addHeader("X-Checksum-Md5", details.md5);
+ return httpPut;
+ }
+
public void uploadChecksums(DeployDetails details, String uploadUrl) throws IOException {
Map<String, String> checksums = getChecksumMap(details);
String fileAbsolutePath = details.file.getAbsolutePath();
View
217 build-info-client/src/main/java/org/jfrog/build/client/ArtifactoryDependenciesClient.java
@@ -0,0 +1,217 @@
+/*
+ * 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.client;
+
+import org.apache.commons.io.IOUtils;
+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.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.type.TypeReference;
+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.util.Log;
+import org.jfrog.build.util.JsonSerializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Artifactory client to perform artifacts and build dependencies related tasks.
+ *
+ * @author Noam Y. Tenne
+ */
+public class ArtifactoryDependenciesClient {
+
+ private String artifactoryUrl;
+
+ private ArtifactoryHttpClient httpClient;
+
+ public ArtifactoryDependenciesClient(String artifactoryUrl, String username, String password, Log logger) {
+ this.artifactoryUrl = StringUtils.stripEnd(artifactoryUrl, "/");
+ httpClient = new ArtifactoryHttpClient(this.artifactoryUrl, username, password, logger);
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ httpClient.setConnectionTimeout(connectionTimeout);
+ }
+
+ public void setProxyConfiguration(String host, int port) {
+ httpClient.setProxyConfiguration(host, port, null, null);
+ }
+
+ public void setProxyConfiguration(String host, int port, String username, String password) {
+ httpClient.setProxyConfiguration(host, port, username, password);
+ }
+
+ public void shutdown() {
+ if (httpClient != null) {
+ httpClient.shutdown();
+ }
+ }
+
+
+ /**
+ * 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.
+ * @throws java.io.IOException
+ */
+ public List<BuildPatternArtifacts> retrievePatternArtifacts(List<BuildPatternArtifactsRequest> requests)
+ throws IOException {
+ final String json = new JsonSerializer<List<BuildPatternArtifactsRequest>>().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);
+
+ List<BuildPatternArtifacts> artifacts = readResponse(httpClient.getHttpClient().execute(post),
+ new TypeReference<List<BuildPatternArtifacts>>() {
+ },
+ "Failed to retrieve build artifacts report");
+ return artifacts;
+ }
+
+
+ public PatternResultFileSet searchArtifactsByPattern(String pattern) throws IOException {
+ PreemptiveHttpClient client = httpClient.getHttpClient();
+
+ String url = artifactoryUrl + "/api/search/pattern?pattern=" + pattern;
+ PatternResultFileSet result = readResponse(client.execute(new HttpGet(url)),
+ new TypeReference<PatternResultFileSet>() {
+ },
+ "Failed to search artifact by the pattern '" + pattern + "'");
+ return result;
+ }
+
+
+ /**
+ * Reads HTTP response and converts it to object of the type specified.
+ *
+ * @param response response to read
+ * @param valueType response object type
+ * @param errorMessage error message to throw in case of error
+ * @param <T> 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> T readResponse(HttpResponse response, TypeReference<T> valueType, String errorMessage)
+ throws IOException {
+
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ HttpEntity entity = response.getEntity();
+ if (entity == null) {
+ return null;
+ }
+
+ InputStream content = null;
+
+ try {
+ content = entity.getContent();
+ JsonParser parser = httpClient.createJsonParser(content);
+ // http://wiki.fasterxml.com/JacksonDataBinding
+ return parser.readValueAs(valueType);
+ } finally {
+ if (content != null) {
+ IOUtils.closeQuietly(content);
+ }
+ }
+ } else {
+ HttpEntity httpEntity = response.getEntity();
+ if (httpEntity != null) {
+ IOUtils.closeQuietly(httpEntity.getContent());
+ }
+ throw new IOException(errorMessage + ": " + response.getStatusLine());
+ }
+ }
+
+
+ public void downloadArtifact(String downloadUrl, File dest) throws IOException {
+ HttpResponse response = executeGet(downloadUrl);
+
+ if (dest.exists()) {
+ dest.delete();
+ dest.createNewFile();
+ } else {
+ dest.getParentFile().mkdirs();
+ dest.createNewFile();
+ }
+ InputStream inputStream = response.getEntity().getContent();
+ FileOutputStream fileOutputStream = new FileOutputStream(dest);
+ try {
+ IOUtils.copyLarge(inputStream, fileOutputStream);
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ IOUtils.closeQuietly(fileOutputStream);
+ response.getEntity().consumeContent();
+ }
+ }
+
+ public String downloadChecksum(String downloadUrl, String checksumAlgorithm) throws IOException {
+ HttpResponse response = executeGet(downloadUrl + "." + checksumAlgorithm);
+
+ InputStream inputStream = response.getEntity().getContent();
+ try {
+ return IOUtils.toString(inputStream);
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ response.getEntity().consumeContent();
+ }
+ }
+
+ private HttpResponse executeGet(String downloadUrl) throws IOException {
+ PreemptiveHttpClient client = httpClient.getHttpClient();
+
+ HttpGet get = new HttpGet(downloadUrl);
+ //Explicitly force keep alive
+ get.setHeader("Connection", "Keep-Alive");
+
+ HttpResponse response = client.execute(get);
+
+ StatusLine statusLine = response.getStatusLine();
+ int statusCode = statusLine.getStatusCode();
+ if (statusCode == HttpStatus.SC_NOT_FOUND) {
+ HttpEntity httpEntity = response.getEntity();
+ if (httpEntity != null) {
+ httpEntity.consumeContent();
+ }
+ throw new FileNotFoundException("Unable to find " + downloadUrl);
+ }
+
+ if (statusCode != HttpStatus.SC_OK) {
+ HttpEntity httpEntity = response.getEntity();
+ if (httpEntity != null) {
+ httpEntity.consumeContent();
+ }
+ throw new IOException("Error downloading " + downloadUrl + ". Code: " + statusCode + " Message: " +
+ statusLine.getReasonPhrase());
+ }
+ return response;
+ }
+}
View
195 build-info-client/src/main/java/org/jfrog/build/util/BuildDependenciesHelper.java
@@ -0,0 +1,195 @@
+/*
+ * 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.util;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringUtils;
+import org.jfrog.build.api.builder.dependency.BuildPatternArtifactsRequestBuilder;
+import org.jfrog.build.api.dependency.BuildPatternArtifacts;
+import org.jfrog.build.api.dependency.BuildPatternArtifactsRequest;
+import org.jfrog.build.api.dependency.PatternResult;
+import org.jfrog.build.api.dependency.UserBuildDependency;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Helper class for parsing build dependencies property.
+ *
+ * @author Evgeny Goldin
+ */
+public class BuildDependenciesHelper {
+
+ public static List<UserBuildDependency> getBuildDependencies(String buildItemsPropertyValue) {
+
+ if (StringUtils.isBlank(buildItemsPropertyValue)) {
+ return Collections.emptyList();
+ }
+
+ // Build name => build number => build dependency
+ Map<String, Map<String, UserBuildDependency>> buildsMap = buildsMap(buildItemsPropertyValue);
+ List<UserBuildDependency> userBuildDependencies = Lists.newLinkedList();
+
+ for (Map<String, UserBuildDependency> m : buildsMap.values()) {
+ for (UserBuildDependency bd : m.values()) {
+ userBuildDependencies.add(bd);
+ }
+ }
+
+ return userBuildDependencies;
+ }
+
+
+ private static Map<String, Map<String, UserBuildDependency>> buildsMap(String buildItemsPropertyValue) {
+ Map<String, Map<String, UserBuildDependency>> buildsMap = Maps.newHashMap();
+ List<String> patternLines = PublishedItemsHelper.parsePatternsFromProperty(buildItemsPropertyValue);
+
+ for (String patternLine : patternLines) {
+ //since the patterns might now include patterns which aren't part of a build, we need to filter those
+ if (patternLine.contains("@")) {
+ /**
+ * Every pattern line is:
+ * "<Artifactory repo>:<pattern>@<build name>#<build number> => <targetDirectory>"
+ * "libs-release-local:com/goldin/plugins/gradle/0.1.1/*.jar@gradle-plugins :: Build :: Gradle#LATEST => many-jars-build"
+ */
+ String[] splitPattern = patternLine.split("=>");
+
+ if (splitPattern.length < 1) {
+ continue;
+ }
+
+ String dependency = FilenameUtils.separatorsToUnix(splitPattern[0].trim());
+ int index1 = dependency.lastIndexOf('@');
+ int index2 = dependency.lastIndexOf('#');
+ boolean lineIsOk = (index1 > 0) && (index2 > index1) && (index2 < (dependency.length() - 1));
+
+ if (!lineIsOk) {
+ continue;
+ }
+
+ String pattern = PublishedItemsHelper.removeDoubleDotsFromPattern(dependency.substring(0, index1));
+ String buildName = dependency.substring(index1 + 1, index2);
+ String buildNumber = dependency.substring(index2 + 1);
+ String targetDirectory = (splitPattern.length > 1) ?
+ PublishedItemsHelper.removeDoubleDotsFromPattern(
+ FilenameUtils.separatorsToUnix(splitPattern[1].trim())) :
+ "";
+
+ if (StringUtils.isBlank(buildName) || StringUtils.isBlank(buildNumber) || StringUtils.isBlank(
+ pattern)) {
+ continue;
+ }
+
+ Map<String, UserBuildDependency> numbersMap = buildsMap.get(buildName);
+
+ if (numbersMap == null) {
+ buildsMap.put(buildName, Maps.<String, UserBuildDependency>newHashMap());
+ numbersMap = buildsMap.get(buildName);
+ }
+
+ UserBuildDependency userBuildDependency = numbersMap.get(buildNumber);
+
+ if (userBuildDependency == null) {
+ numbersMap.put(buildNumber,
+ new UserBuildDependency(buildName, buildNumber, pattern, targetDirectory));
+ } else {
+ userBuildDependency.addPattern(pattern, targetDirectory);
+ }
+ }
+ }
+
+ return buildsMap;
+ }
+
+
+ public static List<BuildPatternArtifactsRequest> toArtifactsRequests(
+ List<UserBuildDependency> userBuildDependencies) {
+ List<BuildPatternArtifactsRequest> artifactsRequests = Lists.newLinkedList();
+
+ for (UserBuildDependency dependencyUser : userBuildDependencies) {
+ BuildPatternArtifactsRequestBuilder builder = new BuildPatternArtifactsRequestBuilder().
+ buildName(dependencyUser.getBuildName()).
+ buildNumber(dependencyUser.getBuildNumberRequest());
+
+ for (UserBuildDependency.Pattern p : dependencyUser.getPatterns()) {
+ builder.pattern(p.getArtifactoryPattern());
+ }
+
+ artifactsRequests.add(builder.build());
+ }
+
+ return artifactsRequests;
+ }
+
+
+ public static void applyBuildArtifacts(List<UserBuildDependency> userBuildDependencies,
+ List<BuildPatternArtifacts> buildArtifacts) {
+
+ verifySameSize(userBuildDependencies, buildArtifacts);
+
+ for (int j = 0; j < userBuildDependencies.size(); j++) {
+
+ UserBuildDependency dependencyUser = userBuildDependencies.get(j);
+ BuildPatternArtifacts artifacts = buildArtifacts.get(j);
+
+ if (artifacts == null) {
+ // Pattern didn't match any results: wrong build name or build number.
+ continue;
+ }
+
+ assert dependencyUser.getBuildName().equals(artifacts.getBuildName()) :
+ String.format("Build names don't match: [%s] != [%s]", dependencyUser.getBuildName(),
+ artifacts.getBuildName());
+
+ dependencyUser.setBuildNumberResponse(artifacts.getBuildNumber());
+ dependencyUser.setBuildStarted(artifacts.getStarted());
+ dependencyUser.setBuildUrl(artifacts.getUrl());
+
+ List<UserBuildDependency.Pattern> dependencyPatterns = dependencyUser.getPatterns();
+ List<PatternResult> patternResults = artifacts.getPatternResults();
+
+ verifySameSize(dependencyPatterns, patternResults);
+
+ for (int k = 0; k < dependencyPatterns.size(); k++) {
+ UserBuildDependency.Pattern p = dependencyPatterns.get(k);
+ PatternResult result = patternResults.get(k);
+ p.setPatternResult(result);
+ }
+ }
+ }
+
+
+ /**
+ * Verifies both lists are of the same size.
+ *
+ * @param l1 first list to check
+ * @param l2 second list to check
+ * @throws IllegalArgumentException if lists are of different sizes.
+ */
+ private static void verifySameSize(List l1, List l2) {
+
+ if (l1.size() != l2.size()) {
+ throw new IllegalArgumentException(
+ String.format("List sizes don't match: [%s] != [%s]", l1.size(), l2.size()));
+ }
+ }
+
+}
View
58 build-info-client/src/main/java/org/jfrog/build/util/DependenciesHelper.java
@@ -0,0 +1,58 @@
+package org.jfrog.build.util;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+/**
+ * Helper class for parsing custom resolved dependencies
+ *
+ * @author Shay Yaakov
+ */
+public abstract class DependenciesHelper {
+
+ public static String extractPatternFromSource(String sourcePattern) {
+ int indexOfSemiColon = sourcePattern.indexOf(';');
+ if (indexOfSemiColon == -1) {
+ return sourcePattern;
+ }
+
+ return sourcePattern.substring(0, indexOfSemiColon);
+ }
+
+ public static String extractMatrixParamsFromSource(String sourcePattern) throws UnsupportedEncodingException {
+ StringBuilder matrixParamBuilder = new StringBuilder();
+
+ //Split pattern to fragments in case there are any matrix params
+ String[] patternFragments = StringUtils.split(sourcePattern, ';');
+
+ //Iterate and add matrix params if there are any
+ if (patternFragments.length > 1) {
+ for (int i = 1; i < patternFragments.length; i++) {
+ String matrixParam = patternFragments[i];
+ String[] matrixParamFragments = StringUtils.split(matrixParam, '=');
+
+ if (matrixParamFragments.length == 0) {
+ continue;
+ }
+ //If the key is mandatory, separate the + before encoding
+ String key = matrixParamFragments[0];
+ boolean mandatory = false;
+ if (key.endsWith("+")) {
+ mandatory = true;
+ key = key.substring(0, key.length() - 1);
+ }
+ matrixParamBuilder.append(URLEncoder.encode(key, "utf-8"));
+ if (mandatory) {
+ matrixParamBuilder.append("+");
+ }
+ if (matrixParamFragments.length > 1) {
+ matrixParamBuilder.append("=").append(URLEncoder.encode(matrixParamFragments[1], "utf-8"));
+ }
+ }
+ }
+
+ return matrixParamBuilder.toString();
+ }
+}
View
8 build-info-client/src/main/java/org/jfrog/build/util/PublishedItemsHelper.java
@@ -18,7 +18,6 @@
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
@@ -27,7 +26,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -47,8 +45,8 @@
* then the value is treated as a source only (target will be "").
* @return a Map containing the sources as keys and targets as values
*/
- public static Map<String, String> getPublishedItemsPatternPairs(String publishedItemsPropertyValue) {
- Map<String, String> patternPairMap = Maps.newHashMap();
+ public static Multimap<String, String> getPublishedItemsPatternPairs(String publishedItemsPropertyValue) {
+ Multimap<String, String> patternPairMap = HashMultimap.create();
if (StringUtils.isNotBlank(publishedItemsPropertyValue)) {
List<String> patternPairs = parsePatternsFromProperty(publishedItemsPropertyValue);
@@ -82,7 +80,7 @@
* @param publishedItemsPropertyValue The property value to split
* @return a List of the splinted parameter by new lines or commas.
*/
- private static List<String> parsePatternsFromProperty(String publishedItemsPropertyValue) {
+ public static List<String> parsePatternsFromProperty(String publishedItemsPropertyValue) {
if (publishedItemsPropertyValue == null) {
throw new IllegalArgumentException("Cannot parse null pattern.");
}
View
29 build-info-client/src/test/java/org/jfrog/build/util/PublishedItemsHelperTest.java
@@ -31,8 +31,8 @@ public void setup() {
}
public void testDoubleDotWithStartWildcard() throws IOException {
- Map<String, String> pairs = getPublishedItemsPatternPairs("../../saas/**/*.xml=>target/xml");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs("../../saas/**/*.xml=>target/xml");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 2, "Expected to find 2 files");
for (Map.Entry<String, File> fileEntry : buildPublishingData.entries()) {
@@ -45,8 +45,9 @@ public void testDoubleDotWithStartWildcard() throws IOException {
}
public void testAbsolutePath() throws IOException {
- Map<String, String> pairs = getPublishedItemsPatternPairs(absoluteFile.getAbsolutePath() + "=>jaja/gululu");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs(
+ absoluteFile.getAbsolutePath() + "=>jaja/gululu");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 1, "Expected to find 1 files");
assertTrue(buildPublishingData.containsValue(absoluteFile), "Expected to find the absolute file");
@@ -60,13 +61,13 @@ public void testAbsolutePath() throws IOException {
public void testMultiPatterns() throws IOException {
String pattern = "**/multi1/*=>test/multi1, **multi2/*=>test/multi2";
- Map<String, String> pairs = getPublishedItemsPatternPairs(pattern);
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs(pattern);
assertEquals(pairs.keySet().size(), 2, "Expected to find 2 keys");
}
public void testAllWorkspace() throws IOException {
- Map<String, String> pairs = getPublishedItemsPatternPairs("**");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs("**");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 6, "Expected to find 6 files");
}
@@ -75,16 +76,16 @@ public void testAllWorkspace() throws IOException {
public void testAbsolutePathWithDoubleStar() throws IOException {
File resourceAsFile = getResourceAsFile("/root/workspace");
String fileAbsolutePath = FilenameUtils.separatorsToUnix(resourceAsFile.getAbsolutePath());
- Map<String, String> pairs = getPublishedItemsPatternPairs(fileAbsolutePath + "/ant/**");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs(fileAbsolutePath + "/ant/**");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 7, "Expected to find 7 files");
}
}
public void testAllSpecificFilesFromCheckoutDir() throws IOException {
- Map<String, String> pairs = getPublishedItemsPatternPairs("**/*.blabla=>blabla");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs("**/*.blabla=>blabla");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 2, "Expected to find 2 files");
for (Map.Entry<String, File> fileEntry : buildPublishingData.entries()) {
@@ -96,8 +97,8 @@ public void testAllSpecificFilesFromCheckoutDir() throws IOException {
}
public void testEmptyTargetPath() throws IOException {
- Map<String, String> pairs = getPublishedItemsPatternPairs("../../**/**/*.xml");
- for (final Map.Entry<String, String> entry : pairs.entrySet()) {
+ Multimap<String, String> pairs = getPublishedItemsPatternPairs("../../**/**/*.xml");
+ for (final Map.Entry<String, String> entry : pairs.entries()) {
Multimap<String, File> buildPublishingData = getBuildPublishingData(entry);
assertEquals(buildPublishingData.size(), 2, "Expected to find 2 files");
for (Map.Entry<String, File> fileEntry : buildPublishingData.entries()) {
@@ -108,7 +109,7 @@ public void testEmptyTargetPath() throws IOException {
}
}
- private Map<String, String> getPublishedItemsPatternPairs(String pattern) {
+ private Multimap<String, String> getPublishedItemsPatternPairs(String pattern) {
return PublishedItemsHelper.getPublishedItemsPatternPairs(pattern);
}
View
2 gradle.properties
@@ -1,5 +1,5 @@
build-info-extractor-gradle-version=2.0.x-SNAPSHOT
-build-info-latest-release-version=2.0.8
+build-info-latest-release-version=2.0.9
build-info-extractor-ivy-version=2.0.x-SNAPSHOT
build-info-with-plugin=true
build-info-version=2.0.x-SNAPSHOT

0 comments on commit b402c2c

Please sign in to comment.
Something went wrong with that request. Please try again.