Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MARP-959: AxonIvy Portal Images and URLs are broken #139

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.axonivy.market.comparator;

import com.axonivy.market.constants.CommonConstants;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.kohsuke.github.GHTag;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.axonivy.market.constants.CommonConstants.DASH_SEPARATOR;
import static com.axonivy.market.constants.MavenConstants.SNAPSHOT_VERSION;
import static org.apache.commons.lang3.StringUtils.EMPTY;

public class MavenVersionComparator {

private static final String MAIN_VERSION_REGEX = "\\.";
private static final int GREATER_THAN = 1;
private static final int EQUAL = 0;
private static final int LESS_THAN = -1;

private MavenVersionComparator() {
}

public static GHTag findHighestTag(List<GHTag> ghTags) {
if (CollectionUtils.isEmpty(ghTags)) {
return null;
}
String highestVersion = findHighestMavenVersion(ghTags.stream().map(GHTag::getName).toList());
return ghTags.stream().filter(tag -> tag.getName().equals(highestVersion)).findAny().orElse(null);
}

public static String findHighestMavenVersion(List<String> versions) {
if (CollectionUtils.isEmpty(versions)) {
return null;
}

String highestVersion = versions.get(0);
for (var version : versions) {
if (compare(version, highestVersion) > EQUAL) {
highestVersion = version;
}
}
return highestVersion;
}

private static int compare(String version, String otherVersion) {
version = stripLeadingChars(version);
otherVersion = stripLeadingChars(otherVersion);
String[] versionParts = createMainAndQualifierArray(version);
String[] otherVersionParts = createMainAndQualifierArray(otherVersion);

// Compare main version parts
int mainComparison = compareMainVersion(versionParts[0], otherVersionParts[0]);
if (mainComparison != EQUAL) {
return mainComparison;
}

// Compare qualifiers
String qualifier1 = getQualifierPart(versionParts);
String qualifier2 = getQualifierPart(otherVersionParts);
// Consider versions without a qualifier higher than those with qualifiers
if (qualifier1.isEmpty() && !qualifier2.isEmpty()) {
return GREATER_THAN;
}
if (!qualifier1.isEmpty() && qualifier2.isEmpty()) {
return LESS_THAN;
}
return compareQualifier(qualifier1, qualifier2);
}

private static String stripLeadingChars(String version) {
Pattern pattern = Pattern.compile(CommonConstants.DIGIT_REGEX);
Matcher matcher = pattern.matcher(version);
if (matcher.find()) {
return matcher.group(1);
}
return version;
}

private static int compareMainVersion(String mainVersion, String otherMainVersion) {
String[] parts1 = mainVersion.split(MAIN_VERSION_REGEX);
String[] parts2 = otherMainVersion.split(MAIN_VERSION_REGEX);

int length = Math.max(parts1.length, parts2.length);
for (int i = 0; i < length; i++) {
int num1 = parseToNumber(parts1, i);
int num2 = parseToNumber(parts2, i);
if (num1 != num2) {
return num1 - num2;
}
}
return EQUAL;
}

private static String getQualifierPart(String[] versionParts) {
return versionParts.length > 1 ? versionParts[1] : EMPTY;
}

private static String[] createMainAndQualifierArray(String version) {
return StringUtils.defaultIfBlank(version, EMPTY).split(DASH_SEPARATOR, 2);
}

private static int parseToNumber(String[] versionParts, int index) {
if (index < versionParts.length && NumberUtils.isDigits(versionParts[index])) {
return NumberUtils.toInt(versionParts[index]);
}
return 0;
}

private static int compareQualifier(String qualifier1, String qualifier2) {
if (SNAPSHOT_VERSION.equals(qualifier1) && !SNAPSHOT_VERSION.equals(qualifier2)) {
return LESS_THAN;
}
if (!SNAPSHOT_VERSION.equals(qualifier1) && SNAPSHOT_VERSION.equals(qualifier2)) {
return GREATER_THAN;
}
return qualifier1.compareTo(qualifier2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.axonivy.market.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class AsyncConfig implements AsyncConfigurer {

private static final String THREAD_NAME_PREFIX = "AC-Thread-";

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.axonivy.market.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulingConfig {

private static final String THREAD_NAME_PREFIX = "SC-Thread-";

@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.setThreadNamePrefix(THREAD_NAME_PREFIX);
taskScheduler.initialize();
return taskScheduler;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public class CommonConstants {
public static final String DASH_SEPARATOR = "-";
public static final String SPACE_SEPARATOR = " ";
public static final String BEARER = "Bearer";
public static final String DIGIT_REGEX = "([0-9]+.*)";
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ public class MavenConstants {
private MavenConstants() {
}

public static final String SNAPSHOT_RELEASE_POSTFIX = "-SNAPSHOT";
public static final String SNAPSHOT_VERSION = "SNAPSHOT";
public static final String SNAPSHOT_RELEASE_POSTFIX = "-" + SNAPSHOT_VERSION;
public static final String SPRINT_RELEASE_POSTFIX = "-m";
public static final String PRODUCT_ARTIFACT_POSTFIX = "-product";
public static final String METADATA_URL_FORMAT = "%s/%s/%s/maven-metadata.xml";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.axonivy.market.service.impl;

import com.axonivy.market.comparator.MavenVersionComparator;
import com.axonivy.market.constants.CommonConstants;
import com.axonivy.market.constants.GitHubConstants;
import com.axonivy.market.constants.ProductJsonConstants;
Expand Down Expand Up @@ -55,13 +56,7 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;

import static com.axonivy.market.enums.DocumentField.MARKET_DIRECTORY;
import static com.axonivy.market.enums.DocumentField.SHORT_DESCRIPTIONS;
Expand Down Expand Up @@ -360,14 +355,11 @@ private void getProductContents(Product product) {
private void updateProductFromReleaseTags(Product product, GHRepository productRepo) {
List<ProductModuleContent> productModuleContents = new ArrayList<>();
List<GHTag> ghTags = getProductReleaseTags(product);
GHTag lastTag = CollectionUtils.firstElement(ghTags);

GHTag lastTag = MavenVersionComparator.findHighestTag(ghTags);
if (lastTag == null || lastTag.getName().equals(product.getNewestReleaseVersion())) {
return;
}

getPublishedDateFromLatestTag(product,
lastTag);
product.setNewestPublishedDate(getPublishedDateFromLatestTag(lastTag));
product.setNewestReleaseVersion(lastTag.getName());

if (!CollectionUtils.isEmpty(product.getReleasedVersions())) {
Expand All @@ -392,12 +384,13 @@ private void updateProductFromReleaseTags(Product product, GHRepository productR
}
}

private void getPublishedDateFromLatestTag(Product product, GHTag lastTag) {
private Date getPublishedDateFromLatestTag(GHTag lastTag) {
try {
product.setNewestPublishedDate(lastTag.getCommit().getCommitDate());
} catch (IOException e) {
return lastTag.getCommit().getCommitDate();
} catch (Exception e) {
log.error("Fail to get commit date ", e);
}
return null;
}

private void updateProductCompatibility(Product product) {
Expand All @@ -414,13 +407,12 @@ private void updateProductCompatibility(Product product) {
}

private List<GHTag> getProductReleaseTags(Product product) {
List<GHTag> tags = new ArrayList<>();
try {
tags = gitHubService.getRepositoryTags(product.getRepositoryName());
return gitHubService.getRepositoryTags(product.getRepositoryName());
} catch (IOException e) {
log.error("Cannot get tag list of product ", e);
}
return tags;
return List.of();
}

// Cover 3 cases after removing non-numeric characters (8, 11.1 and 10.0.2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,10 @@ void testSyncProductsSecondTime() throws IOException {

GHTag mockTag = mock(GHTag.class);
when(mockTag.getName()).thenReturn("v10.0.2");
when(mockTag.getCommit()).thenReturn(mockGHCommit);

GHTag mockTag2 = mock(GHTag.class);
when(mockTag2.getName()).thenReturn("v10.0.3");
when(mockTag2.getCommit()).thenReturn(mockGHCommit);

when(mockGHCommit.getCommitDate()).thenReturn(new Date());
when(gitHubService.getRepositoryTags(anyString())).thenReturn(Arrays.asList(mockTag, mockTag2));
Expand Down
Loading