Newer
Older
package de.tobias.playwall.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import de.tobias.playwall.infrastructure.ArtifactoryConfigurationProperties;
import de.tobias.playwall.model.PluginDescription;
import de.tobias.playwall.model.PluginManifest;
import de.tobias.playwall.model.artifactory.Folder;
import de.tobias.playwall.model.artifactory.Version;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.Comparator;
import java.util.List;
@Service
@AllArgsConstructor
@RegisterReflectionForBinding({PluginDescription.class, PluginManifest.class, Folder.class, Folder.FolderItem.class,
ArtifactoryClient.ArchiveViewSourceRequest.class, ArtifactoryClient.ArchiveViewSourceResponse.class})
public class ArtifactoryClient
{
private final WebClient webClient;
private final ArtifactoryConfigurationProperties configurationProperties;
private final VersionTokenizer versionTokenizer;
private ObjectMapper mapper;
@PostConstruct
private void init()
{
mapper = new ObjectMapper(new YAMLFactory());
mapper.findAndRegisterModules();
}
public Version getLatestVersion(PluginDescription plugin)
{
final ResponseEntity<Folder> folderResponse = webClient.get()
.uri("/artifactory/api/storage/%s/%s/%s".formatted(configurationProperties.getRepository(), configurationProperties.getGroupId().replace(".", "/"), plugin.getName()))
.retrieve()
.toEntity(Folder.class)
.block();
if(folderResponse == null || folderResponse.getBody() == null)
{
return null;
}
final List<Version> version = folderResponse.getBody().getChildren().stream()
.filter(Folder.FolderItem::isFolder)
.map(child -> versionTokenizer.getVersion(child.getUri()))
.sorted(Comparator.comparing(Version::major).thenComparing(Version::minor).thenComparing(Version::patch))
.toList();
if (version.isEmpty()) {
return null;
}
return version.get(version.size() - 1);
record ArchiveViewSourceRequest(String archivePath, String repoKey, String sourcePath)
record ArchiveViewSourceResponse(String source)
{
}
@SneakyThrows
public PluginManifest getPluginManifest(PluginDescription description, Version version)
{
final ResponseEntity<ArchiveViewSourceResponse> response = webClient.post()
.uri("/ui/api/v1/ui/archiveViewSource")
.header("X-Requested-With", "XMLHttpRequest")
.bodyValue(new ArchiveViewSourceRequest(
"%s/%s/%s/%s-%s.jar".formatted(
configurationProperties.getGroupId().replace(".", "/"),
description.getName(),
version.toVersionString(),
description.getName(),
version.toVersionString()
),
configurationProperties.getRepository(),
"plugin.yml"
))
.retrieve()
.toEntity(ArchiveViewSourceResponse.class)
.block();
if(response == null || response.getBody() == null)
{
return null;
}
return mapper.readValue(response.getBody().source(), PluginManifest.class);
}
public Mono<byte[]> downloadArtifact(Plugin plugin)
{
return webClient.get()
.uri("/artifactory/%s/%s/%s/%s/%s-%s.jar".formatted(
configurationProperties.getRepository(),
configurationProperties.getGroupId().replace(".", "/"),
plugin.getName(),
plugin.getVersion(),
plugin.getName(),
plugin.getVersion()
))
.retrieve()
.bodyToMono(byte[].class);
}