Skip to content

Commit 4d53d87

Browse files
authored
Merge pull request #20 from OP-TED/feature/TEDEFO-2401-pre-release-versions-in-sdk-downloader
Refactored SdkDownloader to allow the use of pre-release SDK versions.
2 parents 0c6a3b8 + 9bb032e commit 4d53d87

13 files changed

Lines changed: 247 additions & 83 deletions

File tree

src/main/java/eu/europa/ted/eforms/sdk/SdkVersion.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package eu.europa.ted.eforms.sdk;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
45
import java.util.List;
56
import java.util.Objects;
67
import org.apache.commons.lang3.StringUtils;
@@ -24,27 +25,43 @@ public SdkVersion(final String version) {
2425
}
2526

2627
public String getMajor() {
27-
return version.getMajor().toString();
28+
return this.version.getMajor().toString();
2829
}
2930

3031
public String getMinor() {
31-
return version.getMinor().toString();
32+
return this.version.getMinor().toString();
3233
}
3334

3435
public String getPatch() {
35-
return version.getPatch() == null ? "0" : version.getPatch().toString();
36+
return this.version.getPatch() == null ? "0" : this.version.getPatch().toString();
3637
}
3738

3839
public String getNextMajor() {
39-
return version.withIncMajor().toString();
40+
return this.version.withIncMajor().toString();
4041
}
4142

4243
public String getNextMinor() {
43-
return version.withIncMinor().toString();
44+
return this.version.withIncMinor().toString();
45+
}
46+
47+
public boolean isMajor() {
48+
return !this.isMinor() && this.version.getMajor() != null;
49+
}
50+
51+
public boolean isMinor() {
52+
return !this.isPatch() && this.version.getMinor() != null;
4453
}
4554

4655
public boolean isPatch() {
47-
return version.getPatch() != null;
56+
return this.version.getPatch() != null;
57+
}
58+
59+
public boolean isPreRelease() {
60+
return this.version.getSuffixTokens().length > 0;
61+
}
62+
63+
public boolean isSnapshot() {
64+
return Arrays.asList(this.version.getSuffixTokens()).contains("SNAPSHOT");
4865
}
4966

5067
public String toNormalisedString(boolean withPatch) {
@@ -66,7 +83,7 @@ public String toStringWithoutPatch() {
6683

6784
@Override
6885
public String toString() {
69-
return version.toString();
86+
return this.version.toString();
7087
}
7188

7289
@Override
@@ -79,12 +96,12 @@ public int compareTo(SdkVersion that) {
7996
return 0;
8097
}
8198

82-
return version.compareTo(that.version);
99+
return this.version.compareTo(that.version);
83100
}
84101

85102
@Override
86103
public int hashCode() {
87-
return Objects.hash(version);
104+
return Objects.hash(this.version);
88105
}
89106

90107
@Override
@@ -96,6 +113,6 @@ public boolean equals(Object obj) {
96113
if (getClass() != obj.getClass())
97114
return false;
98115
SdkVersion other = (SdkVersion) obj;
99-
return Objects.equals(version, other.version);
116+
return Objects.equals(this.version, other.version);
100117
}
101118
}

src/main/java/eu/europa/ted/eforms/sdk/resource/SdkDownloader.java

Lines changed: 166 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
import java.nio.file.Files;
55
import java.nio.file.Path;
66
import java.text.MessageFormat;
7+
import java.util.List;
78
import java.util.NoSuchElementException;
89
import java.util.Optional;
10+
import java.util.stream.Collectors;
11+
912
import org.apache.commons.collections.CollectionUtils;
1013
import org.apache.commons.lang3.Validate;
1114
import org.eclipse.aether.artifact.Artifact;
@@ -25,31 +28,29 @@
2528
public class SdkDownloader {
2629
private static final Logger logger = LoggerFactory.getLogger(SdkDownloader.class);
2730

28-
private SdkDownloader() {}
31+
private SdkDownloader() {
32+
}
2933

3034
/**
31-
* Downloads a SDK version from Maven Central (or local Maven repository) and unpacks it under the
32-
* given root directory. - If a major version is requested (e.g., "1"), then the latest
33-
* minor/patch will be fetched and will be stored under a directory
34-
* "<root_directory>/<minor>". - If a minor version is requested (e.g., "1.1"), then
35-
* the latest patch for this minor will be fetched and will be stored under a directory
36-
* "<root_directory>/<minor>" - If a patch is request (e.g., "1.1.2"), then that patch
37-
* will be fetched and will be stored under a directory
38-
* "<root_directory>/<minor>/<patch>". If the requested patch is not found, then
39-
* an {@link IllegalArgumentException} will be thrown.
35+
* Downloads a SDK version from Maven Central (or local Maven repository) and
36+
* unpacks it in a subfolder under the given root directory.
37+
*
38+
* If the given version is not specific enough (e.g. 1.0), its latest
39+
* patch version will be downloaded.
4040
*
41-
* @param sdkVersion The target SDK version (<major>.<minor>.<patch>)
42-
* @param rootDir The root directory
43-
* @throws IOException if the download fails
41+
* @param sdkVersion The SDK version to download.
42+
* @param rootDir The root directory where the SDK will be downloaded
43+
* @param includeSnapshots If true, the latest snapshot version will be
44+
* downloaded if the given version is not found
45+
* @throws IOException If the download fails.
4446
*/
45-
public static void downloadSdk(final SdkVersion sdkVersion, final Path rootDir)
47+
public static void downloadSdk(final SdkVersion sdkVersion, final Path rootDir, boolean includeSnapshots)
4648
throws IOException {
47-
Path sdkDir =
48-
Path.of(Optional.ofNullable(rootDir).orElse(SdkConstants.DEFAULT_SDK_ROOT).toString(),
49-
sdkVersion.isPatch() ? sdkVersion.toString() : sdkVersion.toStringWithoutPatch());
49+
Path sdkDir = Path.of(Optional.ofNullable(rootDir).orElse(SdkConstants.DEFAULT_SDK_ROOT).toString(),
50+
sdkVersion.isPatch() ? sdkVersion.toString() : sdkVersion.toStringWithoutPatch());
5051

5152
try {
52-
SdkVersion artifactVersion = getLatestSdkVersion(sdkVersion);
53+
SdkVersion artifactVersion = getLatestSdkVersion(sdkVersion, includeSnapshots);
5354

5455
if (sdkExistsAt(artifactVersion, sdkDir)) {
5556
logger.debug("SDK [{}] found at [{}]. No download required.", artifactVersion, sdkDir);
@@ -77,16 +78,88 @@ public static void downloadSdk(final SdkVersion sdkVersion, final Path rootDir)
7778
}
7879
}
7980

81+
/**
82+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)} that excludes snapshot versions.
83+
*
84+
* @param sdkVersion The SDK version to download.
85+
* @param rootDir The root directory where the SDK will be downloaded.
86+
* @throws IOException If the download fails.
87+
*/
88+
public static void downloadSdk(final SdkVersion sdkVersion, final Path rootDir)
89+
throws IOException {
90+
downloadSdk(sdkVersion, rootDir, false);
91+
}
92+
93+
/**
94+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
95+
*
96+
* @param sdkVersion The SDK version to download.
97+
* @throws IOException If the download fails.
98+
*/
8099
public static void downloadSdk(final String sdkVersion) throws IOException {
81-
downloadSdk(sdkVersion, SdkConstants.DEFAULT_SDK_ROOT);
100+
downloadSdk(sdkVersion, false);
82101
}
83102

103+
/**
104+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
105+
*
106+
* @param sdkVersion The SDK version to download.
107+
* @param includeSnapshots If true, then SNAPSHOT versions will be downloaded if
108+
* no other version is available.
109+
* @throws IOException If the download fails.
110+
*/
111+
public static void downloadSdk(final String sdkVersion, boolean includeSnapshots) throws IOException {
112+
downloadSdk(sdkVersion, SdkConstants.DEFAULT_SDK_ROOT, includeSnapshots);
113+
}
114+
115+
/**
116+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
117+
*
118+
* @param sdkVersion The SDK version to download.
119+
* @throws IOException If the download fails.
120+
*/
84121
public static void downloadSdk(final SdkVersion sdkVersion) throws IOException {
85-
downloadSdk(sdkVersion, SdkConstants.DEFAULT_SDK_ROOT);
122+
downloadSdk(sdkVersion, false);
86123
}
87124

125+
/**
126+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
127+
*
128+
* @param sdkVersion The SDK version to download.
129+
* @param includeSnapshots If true, then SNAPSHOT versions will be downloaded if
130+
* no other version is available.
131+
* @throws IOException If the download fails.
132+
*/
133+
public static void downloadSdk(final SdkVersion sdkVersion, boolean includeSnapshots) throws IOException {
134+
downloadSdk(sdkVersion, SdkConstants.DEFAULT_SDK_ROOT, includeSnapshots);
135+
}
136+
137+
/**
138+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
139+
*
140+
* @param sdkVersion The SDK version to download.
141+
* @param rootDir The root directory to download the SDK to.
142+
* @throws IOException If the download fails.
143+
*/
88144
public static void downloadSdk(final String sdkVersion, final Path rootDir) throws IOException {
89-
downloadSdk(new SdkVersion(sdkVersion), rootDir);
145+
downloadSdk(sdkVersion, rootDir, false);
146+
}
147+
148+
/**
149+
* Overload of {@link #downloadSdk(SdkVersion, Path, boolean)}.
150+
*
151+
* If the version is not specific enough (i.e. does not include a patch
152+
* version), then the latest available version will be downloaded.
153+
*
154+
* @param sdkVersion The SDK version to download.
155+
* @param rootDir The root directory to download the SDK to.
156+
* @param includeSnapshots If true, then SNAPSHOT versions will be downloaded if
157+
* no other version is available.
158+
* @throws IOException If the download fails.
159+
*/
160+
public static void downloadSdk(final String sdkVersion, final Path rootDir, boolean includeSnapshots)
161+
throws IOException {
162+
downloadSdk(new SdkVersion(sdkVersion), rootDir, includeSnapshots);
90163
}
91164

92165
private static Path createVersionFile(final SdkVersion sdkVersion, final Path sdkDir)
@@ -119,70 +192,92 @@ private static boolean sdkExistsAt(final SdkVersion sdkVersion, final Path sdkDi
119192
}
120193

121194
/**
122-
* Discovers the latest available version for a given base version. If the major of the base
123-
* version is zero, then the second digit is regarded as major. E.g.: - For base version 0.6, the
124-
* result is the largest found version number between 0.6 and 0.7 - For base version 1.0, the
125-
* result is the largest found version number between 1.0 and 1.1
195+
* Discovers the latest available version for a given base version.
126196
*
127-
* @param sdkVersion The base version
128-
* @return
197+
* @param sdkVersion The base version to look for.
198+
* @param includeSnapshots Whether to resolve SNAPSHOT versions if needed (e.g.,
199+
* 1.0.0-SNAPSHOT)
200+
* @return The latest available version.
129201
*/
130-
private static SdkVersion getLatestSdkVersion(final SdkVersion baseVersion)
202+
private static SdkVersion getLatestSdkVersion(final SdkVersion baseVersion, final boolean includeSnapshots)
131203
throws VersionRangeResolutionException {
132204
Validate.notNull(baseVersion, "Undefined base version");
133205

134-
String minVersion = baseVersion.toString();
135-
String maxVersion = baseVersion.getNextMinor();
136-
String searchPattern = "[{0},{1}-SNAPSHOT)";
137-
138-
if (baseVersion.isPatch()) {
139-
minVersion = maxVersion = baseVersion.toString();
140-
searchPattern = "[{0},{1}]";
206+
try {
207+
return getHighestVersion(resolveVersionRange(getSearchPattern(baseVersion)), includeSnapshots);
208+
} catch (NoSuchElementException e1) {
209+
throw new IllegalArgumentException(
210+
MessageFormat.format("No artifacts found for SDK {0}.", baseVersion));
141211
}
212+
}
142213

143-
Artifact artifact = new DefaultArtifact(SdkConstants.SDK_GROUP_ID, SdkConstants.SDK_ARTIFACT_ID,
144-
"jar", MessageFormat.format(searchPattern, minVersion, maxVersion));
214+
/**
215+
* Defines the search pattern for release versions of a given SDK version.
216+
*
217+
* @param sdkVersion The base version to construct the search pattern for.
218+
* @return A search pattern for release versions of the given base version.
219+
*/
220+
private static String getSearchPattern(SdkVersion sdkVersion) {
221+
if (sdkVersion.isPatch()) {
222+
return MessageFormat.format("[{0}]", sdkVersion.toString());
223+
}
224+
return MessageFormat.format("[{0}.*]", sdkVersion.toString());
225+
}
145226

146-
VersionRangeResult versions = MavenBooter.resolveVersionRange(artifact);
147-
try {
148-
/**
149-
* If the major version is "0", Maven will return all the versions up to the next major. In
150-
* this case we need to filter out all the discovered versions where the minor is not the same
151-
* as that of the base version.
152-
*/
153-
if (baseVersion.getMajor().equals("0")) {
154-
return versions.getVersions().stream()
155-
.map(Object::toString)
156-
.map(SdkVersion::new)
157-
.filter((SdkVersion v) -> v.getMajor().equals(baseVersion.getMajor())
158-
&& v.getMinor().equals(baseVersion.getMinor()))
159-
.max(Comparable::compareTo)
160-
.orElseThrow();
161-
} else {
162-
Version highestVersion = versions.getHighestVersion();
227+
/**
228+
* Uses Maven to resolve a version range from a given search pattern.
229+
*
230+
* @param searchPattern The search pattern to resolve.
231+
* @return A version range result.
232+
* @throws VersionRangeResolutionException If the version range could not be
233+
* resolved.
234+
*/
235+
private static VersionRangeResult resolveVersionRange(String searchPattern) throws VersionRangeResolutionException {
236+
Artifact artifact = new DefaultArtifact(SdkConstants.SDK_GROUP_ID, SdkConstants.SDK_ARTIFACT_ID, "jar",
237+
searchPattern);
238+
return MavenBooter.resolveVersionRange(artifact);
239+
}
163240

164-
if (highestVersion == null) {
165-
throw new NoSuchElementException();
166-
}
241+
/**
242+
* Gets the highest version from a version range.
243+
* A pre-release version will be returned only if there is no released version in the range.
244+
*
245+
* @param versionRange The version range to search.
246+
* @param includeSnapshots Whether to include SNAPSHOT versions.
247+
* @return The highest version found.
248+
* @throws NoSuchElementException If the version range is empty.
249+
*/
250+
private static SdkVersion getHighestVersion(VersionRangeResult versionRange, boolean includeSnapshots) throws NoSuchElementException {
251+
252+
List<Version> rangeVersions = versionRange.getVersions();
167253

168-
return new SdkVersion(highestVersion.toString());
169-
}
170-
} catch (NoSuchElementException e) {
171-
String snapshotVersion = MessageFormat.format("{0}.{1}.{2}-SNAPSHOT", baseVersion.getMajor(), baseVersion.getMinor(), baseVersion.getPatch());
172-
logger.warn("No artifacts were found for SDK version [{}]. Trying with [{}]", baseVersion,
173-
snapshotVersion);
254+
if (CollectionUtils.isEmpty(rangeVersions)) {
255+
throw new NoSuchElementException();
256+
}
174257

175-
artifact = new DefaultArtifact(MessageFormat.format("{0}:{1}:{2}", SdkConstants.SDK_GROUP_ID,
176-
SdkConstants.SDK_ARTIFACT_ID, snapshotVersion));
258+
// Get all the versions in the range into a list of SdkVersion objects.
259+
// Exclude snapshots if requested.
260+
List<SdkVersion> allVersions = rangeVersions.stream()
261+
.map(Object::toString)
262+
.map(SdkVersion::new)
263+
.filter(v -> includeSnapshots || !v.isSnapshot())
264+
.collect(Collectors.toList());
177265

178-
versions = MavenBooter.resolveVersionRange(artifact);
266+
// Get all the release versions into a separate list.
267+
// Make sure to include snapshots if requested.
268+
List<SdkVersion> releaseVersions = allVersions.stream()
269+
.filter(v -> !v.isPreRelease() || (v.isSnapshot() && includeSnapshots))
270+
.collect(Collectors.toList());
179271

180-
if (CollectionUtils.isEmpty(versions.getVersions())) {
181-
throw new IllegalArgumentException(
182-
MessageFormat.format("No artifacts were found for SDK version [{0}]", snapshotVersion));
183-
}
272+
// We will only consider pre-release versions if there are no release versions.
273+
List<SdkVersion> eligibleVersions = CollectionUtils.isEmpty(releaseVersions) ? allVersions : releaseVersions;
184274

185-
return new SdkVersion(versions.getVersions().get(0).toString());
275+
// If there are no eligible versions, then throw an exception.
276+
if (CollectionUtils.isEmpty(eligibleVersions)) {
277+
throw new NoSuchElementException();
186278
}
279+
280+
// We can simply return the last version from the list, as Maven sorts versions as we need.
281+
return eligibleVersions.get(eligibleVersions.size() -1);
187282
}
188283
}

0 commit comments

Comments
 (0)