From 4007f3216d054637172c9cb4504cefd02751ea4c Mon Sep 17 00:00:00 2001 From: Andreas Dinauer Date: Sat, 25 Apr 2026 12:25:59 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Big=20Refactoring=20+=20Su?= =?UTF-8?q?pport=20for=20Snapshots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dev/dinauer/maven/Dev.java | 15 +- .../dinauer/maven/app/ArtifactResource.java | 14 +- .../dev/dinauer/maven/app/GroupResource.java | 4 +- .../maven/jpa/maven/repo/VersionRepo.java | 17 -- .../{jpa/maven => maven/core}/ArtifactId.java | 47 +++- .../repo => maven/core}/ArtifactRepo.java | 3 +- .../maven/maven/core/ArtifactService.java | 22 +- .../{jpa/maven => maven/core}/GroupId.java | 2 +- .../maven/repo => maven/core}/GroupRepo.java | 5 +- .../maven/maven/core/GroupService.java | 2 - .../dinauer/maven/maven/core/JarService.java | 72 ------ .../maven/core/MavenContextProvider.java | 33 ++- .../maven/maven/core/MavenService.java | 113 ++++++++++ .../dinauer/maven/maven/core/PomService.java | 65 ------ .../dev/dinauer/maven/maven/core/Service.java | 130 ----------- .../dev/dinauer/maven/maven/core/Version.java | 6 + .../maven/maven/core/VersionService.java | 58 ----- .../maven/core/context/ArtifactContext.java | 39 ++++ .../maven/core/context/ReleaseContext.java | 21 ++ .../maven/core/context/SnapshotContext.java | 42 ++++ .../maven/core/context/VersionContext.java | 32 +++ .../maven/core/model/ExtensionParser.java | 16 +- .../maven/maven/core/model/MavenContext.java | 77 ++++++- .../maven/core/model/SnapshotFileParser.java | 80 ------- .../maven/maven/core/model/Version.java | 35 ++- .../maven/core/parser/MavenUrlParser.java | 11 +- .../core/release/ReleaseJar.java} | 45 ++-- .../maven/core/release/ReleaseJarRepo.java | 61 ++++++ .../maven/core/release/ReleaseJarService.java | 73 +++++++ .../core/release/ReleasePom.java} | 30 +-- .../maven/core/release/ReleasePomRepo.java | 41 ++++ .../maven/core/release/ReleasePomService.java | 62 ++++++ .../maven/core/release/ReleaseService.java | 59 +++++ .../core/release/ReleaseVersion.java} | 64 +++--- .../core/release/ReleaseVersionRepo.java | 29 +++ .../core/release/ReleaseVersionService.java | 33 +++ .../core/release/parser/ReleaseFile.java | 17 ++ .../release/parser/ReleaseFileParser.java | 38 ++++ .../maven/maven/core/{ => rest}/Resource.java | 15 +- .../maven/core/snapshot/SnapshotBundle.java | 110 ++++++++++ .../core/snapshot/SnapshotBundleRepo.java | 15 ++ .../core/snapshot/SnapshotBundleService.java | 50 +++++ .../maven/core/snapshot/SnapshotFile.java | 53 +++++ .../maven/core/snapshot/SnapshotJar.java | 91 ++++++++ .../maven/core/snapshot/SnapshotJarRepo.java | 52 +++++ .../core/snapshot/SnapshotJarService.java | 64 ++++++ .../maven/core/snapshot/SnapshotPom.java | 81 +++++++ .../maven/core/snapshot/SnapshotPomRepo.java | 31 +++ .../core/snapshot/SnapshotPomService.java | 62 ++++++ .../maven/core/snapshot/SnapshotService.java | 52 +++++ .../maven/core/snapshot/SnapshotVersion.java | 79 +++++++ .../core/snapshot/SnapshotVersionRepo.java | 16 ++ .../core/snapshot/SnapshotVersionService.java | 51 +++++ .../snapshot/parser/SnapshotFileParser.java | 50 +++++ .../maven/maven/shared/Extensions.java | 10 + .../maven/maven/shared/GenericFile.java | 5 + .../maven/maven/shared/MavenCoordinates.java | 5 + .../dinauer/maven/maven/shared/Parser.java | 6 + .../maven/maven/shared/ParserResult.java | 5 + src/main/resources/application.properties | 20 +- .../resources/db/migration/V1.0.0__init.sql | 205 ++++++++++++------ .../maven/maven/core/ResourceTest.java | 54 +++-- .../maven/core/model/ExtensionParserTest.java | 28 +-- .../core/model/SnapshotFileParserTest.java | 21 -- .../core/release/ReleaseServiceTest.java | 20 ++ .../core/snapshot/SnapshotServiceTest.java | 20 ++ .../parser/SnapshotFileParserTest.java | 21 ++ 67 files changed, 2112 insertions(+), 693 deletions(-) delete mode 100644 src/main/java/dev/dinauer/maven/jpa/maven/repo/VersionRepo.java rename src/main/java/dev/dinauer/maven/{jpa/maven => maven/core}/ArtifactId.java (62%) rename src/main/java/dev/dinauer/maven/{jpa/maven/repo => maven/core}/ArtifactRepo.java (86%) rename src/main/java/dev/dinauer/maven/{jpa/maven => maven/core}/GroupId.java (97%) rename src/main/java/dev/dinauer/maven/{jpa/maven/repo => maven/core}/GroupRepo.java (84%) delete mode 100644 src/main/java/dev/dinauer/maven/maven/core/JarService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/MavenService.java delete mode 100644 src/main/java/dev/dinauer/maven/maven/core/PomService.java delete mode 100644 src/main/java/dev/dinauer/maven/maven/core/Service.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/Version.java delete mode 100644 src/main/java/dev/dinauer/maven/maven/core/VersionService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/context/ArtifactContext.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/context/ReleaseContext.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/context/SnapshotContext.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/context/VersionContext.java delete mode 100644 src/main/java/dev/dinauer/maven/maven/core/model/SnapshotFileParser.java rename src/main/java/dev/dinauer/maven/{jpa/maven/Jar.java => maven/core/release/ReleaseJar.java} (57%) create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarService.java rename src/main/java/dev/dinauer/maven/{jpa/maven/Pom.java => maven/core/release/ReleasePom.java} (66%) create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleaseService.java rename src/main/java/dev/dinauer/maven/{jpa/maven/Version.java => maven/core/release/ReleaseVersion.java} (61%) create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFile.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFileParser.java rename src/main/java/dev/dinauer/maven/maven/core/{ => rest}/Resource.java (52%) create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundle.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotFile.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJar.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPom.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersion.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionRepo.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionService.java create mode 100644 src/main/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParser.java create mode 100644 src/main/java/dev/dinauer/maven/maven/shared/Extensions.java create mode 100644 src/main/java/dev/dinauer/maven/maven/shared/GenericFile.java create mode 100644 src/main/java/dev/dinauer/maven/maven/shared/MavenCoordinates.java create mode 100644 src/main/java/dev/dinauer/maven/maven/shared/Parser.java create mode 100644 src/main/java/dev/dinauer/maven/maven/shared/ParserResult.java delete mode 100644 src/test/java/dev/dinauer/maven/maven/core/model/SnapshotFileParserTest.java create mode 100644 src/test/java/dev/dinauer/maven/maven/core/release/ReleaseServiceTest.java create mode 100644 src/test/java/dev/dinauer/maven/maven/core/snapshot/SnapshotServiceTest.java create mode 100644 src/test/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParserTest.java diff --git a/src/main/java/dev/dinauer/maven/Dev.java b/src/main/java/dev/dinauer/maven/Dev.java index 578f588..3047143 100644 --- a/src/main/java/dev/dinauer/maven/Dev.java +++ b/src/main/java/dev/dinauer/maven/Dev.java @@ -1,12 +1,9 @@ package dev.dinauer.maven; -import dev.dinauer.maven.maven.core.Service; +import dev.dinauer.maven.maven.core.release.ReleaseService; import io.quarkus.arc.profile.IfBuildProfile; -import io.quarkus.runtime.Startup; -import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; import java.io.IOException; import java.nio.file.Files; @@ -16,16 +13,8 @@ import java.nio.file.Path; @IfBuildProfile("dev") public class Dev { - @Inject - Service service; - @GET - public void init() throws IOException + public void init() { - service.upload("/org/postgresql/postgresql/41.4.9/postgresql-41.4.9.jar", Files.readAllBytes(Path.of("/home/andreas/Documents/dev/maven/core/src/main/resources/jar/postgresql-42.7.9.jar"))).close(); - service.upload("/org/postgresql/postgresql/41.4.9/postgresql-41.4.9.pom", Files.readAllBytes(Path.of("/home/andreas/Documents/dev/maven/core/src/main/resources/jar/postgresql-42.7.9.pom"))).close(); - - service.upload("/com/fasterxml/jackson/core/jackson-core/2.21.0/jackson-core-2.21.0.jar", Files.readAllBytes(Path.of("/home/andreas/Documents/dev/maven/core/src/main/resources/jar/jackson-core-2.21.0.jar"))).close(); - service.upload("/com/fasterxml/jackson/core/jackson-core/2.21.0/jackson-core-2.21.0.pom", Files.readAllBytes(Path.of("/home/andreas/Documents/dev/maven/core/src/main/resources/jar/jackson-core-2.21.0.pom"))).close(); } } \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/app/ArtifactResource.java b/src/main/java/dev/dinauer/maven/app/ArtifactResource.java index b0093da..ddf94b7 100644 --- a/src/main/java/dev/dinauer/maven/app/ArtifactResource.java +++ b/src/main/java/dev/dinauer/maven/app/ArtifactResource.java @@ -1,9 +1,9 @@ package dev.dinauer.maven.app; +import dev.dinauer.maven.maven.core.ArtifactRepo; import dev.dinauer.maven.user.User; -import dev.dinauer.maven.jpa.maven.Version; -import dev.dinauer.maven.jpa.maven.repo.ArtifactRepo; -import dev.dinauer.maven.jpa.maven.ArtifactId; +import dev.dinauer.maven.maven.core.release.ReleaseVersion; +import dev.dinauer.maven.maven.core.ArtifactId; import dev.dinauer.maven.user.UserClient; import jakarta.inject.Inject; import jakarta.transaction.Transactional; @@ -53,9 +53,9 @@ public class ArtifactResource Map accounts = getAccounts(artifactIds); for (ArtifactId artifactId : artifactIds) { - for (Version version : artifactId.getVersions()) + for (ReleaseVersion releaseVersion : artifactId.getVersions()) { - version.setUploadAccount(accounts.get(version.getUploadedBy())); + releaseVersion.setUploadAccount(accounts.get(releaseVersion.getUploadedBy())); } } return artifactIds; @@ -66,9 +66,9 @@ public class ArtifactResource List ids = new ArrayList<>(); for (ArtifactId artifactId : artifactIds) { - for (Version version : artifactId.getVersions()) + for (ReleaseVersion releaseVersion : artifactId.getVersions()) { - ids.add(version.getUploadedBy()); + ids.add(releaseVersion.getUploadedBy()); } } diff --git a/src/main/java/dev/dinauer/maven/app/GroupResource.java b/src/main/java/dev/dinauer/maven/app/GroupResource.java index 26ec499..1c7d6c6 100644 --- a/src/main/java/dev/dinauer/maven/app/GroupResource.java +++ b/src/main/java/dev/dinauer/maven/app/GroupResource.java @@ -1,7 +1,7 @@ package dev.dinauer.maven.app; -import dev.dinauer.maven.jpa.maven.repo.GroupRepo; -import dev.dinauer.maven.jpa.maven.GroupId; +import dev.dinauer.maven.maven.core.GroupRepo; +import dev.dinauer.maven.maven.core.GroupId; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.DELETE; diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/repo/VersionRepo.java b/src/main/java/dev/dinauer/maven/jpa/maven/repo/VersionRepo.java deleted file mode 100644 index 7cab6a0..0000000 --- a/src/main/java/dev/dinauer/maven/jpa/maven/repo/VersionRepo.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.dinauer.maven.jpa.maven.repo; - -import dev.dinauer.maven.jpa.maven.Version; -import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; -import io.quarkus.panache.common.Parameters; -import jakarta.enterprise.context.ApplicationScoped; - -import java.util.Optional; - -@ApplicationScoped -public class VersionRepo implements PanacheRepositoryBase -{ - public Optional findOptionalByVersion(String groupId, String artifactId, String version) - { - return find("version = :version AND artifact.artifactId = :artifactId AND artifact.group.groupId = :groupId", Parameters.with("groupId", groupId).and("artifactId", artifactId).and("version", version)).firstResultOptional(); - } -} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/ArtifactId.java b/src/main/java/dev/dinauer/maven/maven/core/ArtifactId.java similarity index 62% rename from src/main/java/dev/dinauer/maven/jpa/maven/ArtifactId.java rename to src/main/java/dev/dinauer/maven/maven/core/ArtifactId.java index 451ff60..d463f70 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/ArtifactId.java +++ b/src/main/java/dev/dinauer/maven/maven/core/ArtifactId.java @@ -1,17 +1,16 @@ -package dev.dinauer.maven.jpa.maven; +package dev.dinauer.maven.maven.core; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; +import dev.dinauer.maven.maven.core.release.ReleaseVersion; +import dev.dinauer.maven.maven.core.snapshot.SnapshotVersion; import jakarta.persistence.*; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Objects; @Entity @Table(name = "artifact_id") @@ -34,7 +33,11 @@ public class ArtifactId @OneToMany(mappedBy = "artifact", cascade = CascadeType.REMOVE) @JsonManagedReference - private List versions = new ArrayList<>(); + private List releaseVersions = new ArrayList<>(); + + @OneToMany(mappedBy = "artifact", cascade = CascadeType.REMOVE) + @JsonManagedReference + private List snapshotVersions = new ArrayList<>(); @Column(name = "updated_at") private ZonedDateTime updatedAt; @@ -86,14 +89,14 @@ public class ArtifactId return this; } - public List getVersions() + public List getVersions() { - return versions.stream().sorted(Comparator.comparing(version -> new DefaultArtifactVersion(version.getVersion()))).toList().reversed(); + return releaseVersions.stream().sorted(Comparator.comparing(version -> new DefaultArtifactVersion(version.getVersion()))).toList().reversed(); } - public ArtifactId setVersions(List versions) + public ArtifactId setVersions(List releaseVersions) { - this.versions = versions; + this.releaseVersions = releaseVersions; return this; } @@ -122,10 +125,32 @@ public class ArtifactId public int getTotalPullCount() { int i = 0; - for (Version version : versions) + for (ReleaseVersion releaseVersion : releaseVersions) { - i = i + version.getPullCount(); + i = i + releaseVersion.getPullCount(); } return i; } + + public List getSnapshotVersions() + { + return snapshotVersions; + } + + public ArtifactId setSnapshotVersions(List snapshotVersions) + { + this.snapshotVersions = snapshotVersions; + return this; + } + + public List getReleaseVersions() + { + return releaseVersions; + } + + public ArtifactId setReleaseVersions(List releaseVersions) + { + this.releaseVersions = releaseVersions; + return this; + } } diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/repo/ArtifactRepo.java b/src/main/java/dev/dinauer/maven/maven/core/ArtifactRepo.java similarity index 86% rename from src/main/java/dev/dinauer/maven/jpa/maven/repo/ArtifactRepo.java rename to src/main/java/dev/dinauer/maven/maven/core/ArtifactRepo.java index 9307b9a..9ce498e 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/repo/ArtifactRepo.java +++ b/src/main/java/dev/dinauer/maven/maven/core/ArtifactRepo.java @@ -1,6 +1,5 @@ -package dev.dinauer.maven.jpa.maven.repo; +package dev.dinauer.maven.maven.core; -import dev.dinauer.maven.jpa.maven.ArtifactId; import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; import io.quarkus.panache.common.Parameters; import jakarta.enterprise.context.ApplicationScoped; diff --git a/src/main/java/dev/dinauer/maven/maven/core/ArtifactService.java b/src/main/java/dev/dinauer/maven/maven/core/ArtifactService.java index 4df550d..a9a05d8 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/ArtifactService.java +++ b/src/main/java/dev/dinauer/maven/maven/core/ArtifactService.java @@ -1,10 +1,8 @@ package dev.dinauer.maven.maven.core; -import dev.dinauer.maven.jpa.maven.ArtifactId; -import dev.dinauer.maven.jpa.maven.GroupId; -import dev.dinauer.maven.jpa.maven.repo.ArtifactRepo; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; import java.time.ZonedDateTime; import java.util.Optional; @@ -29,7 +27,23 @@ public class ArtifactService { GroupId group = groupService.findOrCreate(groupId); group.setUpdatedAt(ZonedDateTime.now()); - return new ArtifactId().setArtifactId(artifactId).setGroup(group).setGroupId(groupId).setCreatedAt(ZonedDateTime.now()); + + ArtifactId created = new ArtifactId().setArtifactId(artifactId).setGroup(group).setGroupId(groupId).setCreatedAt(ZonedDateTime.now()); + artifactRepo.persist(created); + return created; + } + } + + public ArtifactId require(String groupId, String artifactId) + { + Optional artifactOptional = artifactRepo.findOptionalByArtifactId(groupId, artifactId); + if (artifactOptional.isPresent()) + { + return artifactOptional.get(); + } + else + { + throw new NotFoundException(); } } diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/GroupId.java b/src/main/java/dev/dinauer/maven/maven/core/GroupId.java similarity index 97% rename from src/main/java/dev/dinauer/maven/jpa/maven/GroupId.java rename to src/main/java/dev/dinauer/maven/maven/core/GroupId.java index 3465796..96c7651 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/GroupId.java +++ b/src/main/java/dev/dinauer/maven/maven/core/GroupId.java @@ -1,4 +1,4 @@ -package dev.dinauer.maven.jpa.maven; +package dev.dinauer.maven.maven.core; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/repo/GroupRepo.java b/src/main/java/dev/dinauer/maven/maven/core/GroupRepo.java similarity index 84% rename from src/main/java/dev/dinauer/maven/jpa/maven/repo/GroupRepo.java rename to src/main/java/dev/dinauer/maven/maven/core/GroupRepo.java index cfc3e36..e0b586f 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/repo/GroupRepo.java +++ b/src/main/java/dev/dinauer/maven/maven/core/GroupRepo.java @@ -1,6 +1,5 @@ -package dev.dinauer.maven.jpa.maven.repo; +package dev.dinauer.maven.maven.core; -import dev.dinauer.maven.jpa.maven.GroupId; import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; import io.quarkus.panache.common.Parameters; import jakarta.enterprise.context.ApplicationScoped; @@ -14,4 +13,4 @@ public class GroupRepo implements PanacheRepositoryBase { return find("groupId = :groupId", Parameters.with("groupId", groupId)).firstResultOptional(); } -} +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/GroupService.java b/src/main/java/dev/dinauer/maven/maven/core/GroupService.java index 43c6f53..74b300b 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/GroupService.java +++ b/src/main/java/dev/dinauer/maven/maven/core/GroupService.java @@ -1,7 +1,5 @@ package dev.dinauer.maven.maven.core; -import dev.dinauer.maven.jpa.maven.GroupId; -import dev.dinauer.maven.jpa.maven.repo.GroupRepo; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; diff --git a/src/main/java/dev/dinauer/maven/maven/core/JarService.java b/src/main/java/dev/dinauer/maven/maven/core/JarService.java deleted file mode 100644 index 5fd2fce..0000000 --- a/src/main/java/dev/dinauer/maven/maven/core/JarService.java +++ /dev/null @@ -1,72 +0,0 @@ -package dev.dinauer.maven.maven.core; - -import dev.dinauer.maven.jpa.maven.Jar; -import dev.dinauer.maven.jpa.maven.Version; -import dev.dinauer.maven.maven.core.model.MavenContext; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.apache.commons.codec.digest.DigestUtils; - -import java.util.List; - -@ApplicationScoped -public class JarService -{ - @Inject - VersionService versionService; - - public Response store(MavenContext mavenContext, byte[] body) - { - String md5 = DigestUtils.md5Hex(body); - String sha1 = DigestUtils.sha1Hex(body); - Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); - if (!existsJar(version.getJars(), mavenContext.file().getBase())) - { - version.getJars().add(new Jar().setJar(body).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(mavenContext.path()).setFilename(mavenContext.file().getFilename())); - versionService.persist(version); - return Response.status(Response.Status.CREATED).build(); - } - return Response.status(Response.Status.CONFLICT).build(); - } - - public Response find(MavenContext context) - { - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_OCTET_STREAM).entity(findJar(context).getJar()).build(); - } - - public Response findHash(MavenContext context) - { - switch (context.file().getHash()) - { - case SHA1 -> - { - return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(findJar(context).getSha1()).build(); - } - case MD5 -> - { - return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(findJar(context).getMd5()).build(); - } - } - throw new BadRequestException(); - } - - private Jar findJar(MavenContext context) - { - return versionService.findOptional(context.groupId(), context.artifactId(), context.version().getRaw()).orElseThrow().getJarByFilename(context.file().getFilename()).orElseThrow(); - } - - private boolean existsJar(List jars, String fileBase) - { - for (Jar jar : jars) - { - if (fileBase.equals(jar.getFilename())) - { - return true; - } - } - return false; - } -} diff --git a/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java b/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java index d5e2b10..a004754 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java +++ b/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java @@ -1,32 +1,47 @@ package dev.dinauer.maven.maven.core; +import dev.dinauer.maven.maven.core.context.ArtifactContext; +import dev.dinauer.maven.maven.core.context.VersionContext; import dev.dinauer.maven.maven.core.model.*; import dev.dinauer.maven.maven.core.parser.MavenMetadataUrlParser; import dev.dinauer.maven.maven.core.parser.MavenUrlParser; -import org.apache.commons.io.FilenameUtils; +import dev.dinauer.maven.maven.shared.Extensions; +import dev.dinauer.maven.maven.shared.ParserResult; import java.nio.file.Path; public class MavenContextProvider { - public static MavenContext parse(String path) + public static ArtifactContext parse(String path) { - ExtensionParser.Result result = ExtensionParser.parse(Path.of(path).getFileName().toString()); - switch (result.ext()) + ParserResult extensionResult = new ExtensionParser().parse(Path.of(path).getFileName().toString()); + switch (extensionResult.result().ext()) { case JAR, POM -> { MavenUrlParser parser = MavenUrlParser.parse(path); - String artifact = parser.artifactId(); - Version version = parser.version(); - return new MavenContext(path, parser.groupId(), artifact, version, FileParser.parse(artifact, version.getRaw(), Path.of(path).getFileName().toString())); + return new VersionContext(extensionResult.result(), parser.groupId(), parser.artifactId(), extensionResult.remainder(), parser.version()); } case XML -> { - MavenMetadataUrlParser parser = MavenMetadataUrlParser.parse(path); - return new MavenContext(path, parser.groupId(), parser.artifactId(), null, new File().setBase("maven-metadata").setType(result.ext()).setHash(result.hashExt())); + if (isSnapshot(path)) + { + MavenUrlParser parser = MavenUrlParser.parse(path); + return new VersionContext(extensionResult.result(), parser.groupId(), parser.artifactId(), extensionResult.remainder(), parser.version()); + } + else + { + MavenMetadataUrlParser parser = MavenMetadataUrlParser.parse(path); + return new ArtifactContext(extensionResult.result(), parser.groupId(), parser.artifactId(), extensionResult.remainder()); + } } } throw new RuntimeException(); } + + private static boolean isSnapshot(String path) + { + String[] sections = path.split("/"); + return sections[sections.length - 2].endsWith("-SNAPSHOT"); + } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/MavenService.java b/src/main/java/dev/dinauer/maven/maven/core/MavenService.java new file mode 100644 index 0000000..f4680f9 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/MavenService.java @@ -0,0 +1,113 @@ +package dev.dinauer.maven.maven.core; + +import com.fasterxml.jackson.core.JsonProcessingException; +import dev.dinauer.maven.maven.core.context.ArtifactContext; +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import dev.dinauer.maven.maven.core.context.VersionContext; +import dev.dinauer.maven.maven.core.model.*; +import dev.dinauer.maven.maven.core.model.Version; +import dev.dinauer.maven.maven.core.release.ReleaseService; +import dev.dinauer.maven.maven.core.release.parser.ReleaseFile; +import dev.dinauer.maven.maven.core.release.parser.ReleaseFileParser; +import dev.dinauer.maven.maven.core.snapshot.SnapshotFile; +import dev.dinauer.maven.maven.core.snapshot.SnapshotPom; +import dev.dinauer.maven.maven.core.snapshot.SnapshotService; +import dev.dinauer.maven.maven.core.snapshot.parser.SnapshotFileParser; +import dev.dinauer.maven.maven.shared.Extensions; +import dev.dinauer.maven.maven.shared.MavenCoordinates; +import dev.dinauer.maven.maven.shared.ParserResult; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.commons.lang3.NotImplementedException; + +import java.util.List; +import java.util.Objects; + +@ApplicationScoped +public class MavenService +{ + @Inject + ReleaseService releaseService; + + @Inject + SnapshotService snapshotService; + + public void upload(String path, byte[] body) + { + ArtifactContext context = MavenContextProvider.parse(path); + if (context.getClass() == VersionContext.class) + { + if (List.of(FileExt.JAR, FileExt.POM).contains(context.extensions().ext()) && context.extensions().hashExt().isEmpty()) + { + VersionContext versionContext = (VersionContext) context; + if (versionContext.isSnapshot()) + { + snapshotService.upload(toSnapshotContext(versionContext), body); + } + else + { + releaseService.upload(toReleaseContext(versionContext), body); + } + } + if (Objects.equals(FileExt.XML, context.extensions().ext())) + { + throw new NotImplementedException(); // Hand over to XML metadata service + } + } + if (context.getClass() == ArtifactContext.class) + { + throw new NotImplementedException(); // Hand over to XML Snapshot artifact metadata service + } + } + + public Response serve(String path) + { + ArtifactContext context = MavenContextProvider.parse(path); + if (context.getClass() == VersionContext.class) + { + VersionContext versionContext = (VersionContext) context; + if (versionContext.isSnapshot()) + { + return snapshotService.serve(toSnapshotContext(versionContext)); + } + else + { + return releaseService.serve(toReleaseContext(versionContext)); + } + } + throw new BadRequestException(); + } + + private SnapshotContext toSnapshotContext(VersionContext versionContext) + { + ParserResult result = new SnapshotFileParser(versionContext.artifactId(), versionContext.base()).parse(versionContext.filename()); + return new SnapshotContext( + versionContext.extensions(), + versionContext.groupId(), + versionContext.artifactId(), + versionContext.filename(), + versionContext.version(), + result.result().getDate(), + result.result().getTime(), + result.result().getBuildNumber(), + result.result().getClassifier() + ); + } + + private ReleaseContext toReleaseContext(VersionContext versionContext) + { + ParserResult result = new ReleaseFileParser(versionContext.artifactId(), versionContext.base()).parse(versionContext.filename()); + return new ReleaseContext( + versionContext.extensions(), + versionContext.groupId(), + versionContext.artifactId(), + versionContext.filename(), + versionContext.version(), + result.result().getClassifier() + ); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/PomService.java b/src/main/java/dev/dinauer/maven/maven/core/PomService.java deleted file mode 100644 index 9f6c523..0000000 --- a/src/main/java/dev/dinauer/maven/maven/core/PomService.java +++ /dev/null @@ -1,65 +0,0 @@ -package dev.dinauer.maven.maven.core; - -import dev.dinauer.maven.jpa.maven.Pom; -import dev.dinauer.maven.jpa.maven.Version; -import dev.dinauer.maven.maven.core.model.MavenContext; -import dev.dinauer.maven.maven.token.TokenService; -import io.quarkus.security.identity.SecurityIdentity; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.apache.commons.codec.digest.DigestUtils; - -import java.time.ZonedDateTime; - -@ApplicationScoped -public class PomService -{ - @Inject - SecurityIdentity securityIdentity; - - @Inject - VersionService versionService; - - public Response store(MavenContext mavenContext, byte[] body) - { - String md5 = DigestUtils.md5Hex(body); - String sha1 = DigestUtils.sha1Hex(body); - Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); - version.setUploadedBy(securityIdentity.getPrincipal().getName()); - if (version.getPom() == null) - { - version.setPom(new Pom().setPom(new String(body)).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(mavenContext.path()).setFilename(mavenContext.file().getFilename())); - versionService.persist(version); - return Response.status(Response.Status.CREATED).build(); - } - return Response.status(Response.Status.CONFLICT).build(); - } - - public Response findHash(MavenContext context) - { - Version version = versionService.findOptional(context.groupId(), context.artifactId(), context.version().getRaw()).orElseThrow(); - switch (context.file().getHash()) - { - case SHA1 -> - { - return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(version.getPom().getSha1()).build(); - } - case MD5 -> - { - return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(version.getPom().getMd5()).build(); - } - } - throw new BadRequestException(); - } - - public Response find(MavenContext mavenContext) - { - Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); - version.setLastPulled(ZonedDateTime.now()); - version.incrementPullCount(); - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_XML).entity(version.getPom().getPom()).build(); - } -} diff --git a/src/main/java/dev/dinauer/maven/maven/core/Service.java b/src/main/java/dev/dinauer/maven/maven/core/Service.java deleted file mode 100644 index 9be4bd2..0000000 --- a/src/main/java/dev/dinauer/maven/maven/core/Service.java +++ /dev/null @@ -1,130 +0,0 @@ -package dev.dinauer.maven.maven.core; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import dev.dinauer.maven.jpa.maven.ArtifactId; -import dev.dinauer.maven.jpa.maven.Jar; -import dev.dinauer.maven.jpa.maven.Pom; -import dev.dinauer.maven.jpa.maven.Version; -import dev.dinauer.maven.maven.core.model.ExtensionParser; -import dev.dinauer.maven.maven.core.model.File; -import dev.dinauer.maven.maven.token.TokenService; -import dev.dinauer.maven.metadata.Metadata; -import dev.dinauer.maven.maven.core.model.FileHash; -import dev.dinauer.maven.maven.core.model.MavenContext; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.NotFoundException; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import jdk.jshell.spi.ExecutionControl; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.NotImplementedException; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Optional; - -@ApplicationScoped -public class Service -{ - @Inject - ArtifactService artifactService; - - @Inject - JarService jarService; - - @Inject - PomService pomService; - - @Transactional - public Response upload(String path, byte[] body) - { - MavenContext mavenContext = MavenContextProvider.parse(path); - switch (mavenContext.file().getType()) - { - case JAR -> - { - if (mavenContext.version().getSnapshot()) - { - throw new WebApplicationException(501); - } - if (FileHash.NONE.equals(mavenContext.file().getHash())) - { - return jarService.store(mavenContext, body); - } - return Response.accepted().build(); - } - case POM -> - { - if (mavenContext.version().getSnapshot()) - { - throw new WebApplicationException(501); - } - if (FileHash.NONE.equals(mavenContext.file().getHash())) - { - return pomService.store(mavenContext, body); - } - return Response.accepted().build(); - } - case XML -> - { - return Response.accepted().build(); - } - } - throw new RuntimeException(); - } - - @Transactional - public Response serve(String path) throws JsonProcessingException - { - MavenContext mavenContext = MavenContextProvider.parse(path); - switch (mavenContext.file().getType()) - { - case JAR -> - { - if (FileHash.NONE.equals(mavenContext.file().getHash())) - { - return jarService.find(mavenContext); - } - return jarService.findHash(mavenContext); - } - case POM -> - { - if (FileHash.NONE.equals(mavenContext.file().getHash())) - { - return pomService.find(mavenContext); - } - return pomService.findHash(mavenContext); - } - case XML -> - { - Optional artifactOptional = artifactService.find(mavenContext.groupId(), mavenContext.artifactId()); - if (artifactOptional.isPresent()) - { - ArtifactId artifact = artifactOptional.get(); - String metadata = new XmlMapper().writeValueAsString(new Metadata(artifact.getGroupId(), artifact.getArtifactId(), null, artifact.getUpdatedAt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))); - if (mavenContext.file().getHash() == null) - { - return Response.ok().type(MediaType.APPLICATION_XML).entity(metadata).build(); - } - switch (mavenContext.file().getHash()) - { - case SHA1 -> - { - return Response.ok().type(MediaType.TEXT_PLAIN).entity(DigestUtils.sha1Hex(metadata)).build(); - } - case MD5 -> - { - return Response.ok().type(MediaType.TEXT_PLAIN).entity(DigestUtils.md5Hex(metadata)).build(); - } - } - } - return Response.status(Response.Status.NOT_FOUND).build(); - } - } - throw new RuntimeException(); - } -} diff --git a/src/main/java/dev/dinauer/maven/maven/core/Version.java b/src/main/java/dev/dinauer/maven/maven/core/Version.java new file mode 100644 index 0000000..191f6c1 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/Version.java @@ -0,0 +1,6 @@ +package dev.dinauer.maven.maven.core; + +public interface Version +{ + boolean isSnapshot(); +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/VersionService.java b/src/main/java/dev/dinauer/maven/maven/core/VersionService.java deleted file mode 100644 index 7e0478f..0000000 --- a/src/main/java/dev/dinauer/maven/maven/core/VersionService.java +++ /dev/null @@ -1,58 +0,0 @@ -package dev.dinauer.maven.maven.core; - -import dev.dinauer.maven.event.Event; -import dev.dinauer.maven.event.EventType; -import dev.dinauer.maven.event.Resource; -import dev.dinauer.maven.event.repo.EventRepo; -import dev.dinauer.maven.jpa.maven.ArtifactId; -import dev.dinauer.maven.jpa.maven.Version; -import dev.dinauer.maven.jpa.maven.repo.VersionRepo; -import dev.dinauer.maven.maven.token.TokenService; -import io.quarkus.security.identity.SecurityIdentity; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.time.ZonedDateTime; -import java.util.Optional; - -@ApplicationScoped -public class VersionService -{ - @Inject - VersionRepo versionRepo; - - @Inject - ArtifactService artifactService; - - @Inject - EventRepo eventRepo; - - @Inject - SecurityIdentity securityIdentity; - - public Optional findOptional(String groupId, String artifactId, String version) - { - return versionRepo.findOptionalByVersion(groupId, artifactId, version); - } - - public Version findOrCreate(String groupId, String artifactId, String version) - { - Optional versionOptional = versionRepo.findOptionalByVersion(groupId, artifactId, version); - if (versionOptional.isPresent()) - { - return versionOptional.get(); - } - else - { - ArtifactId artifact = artifactService.findOrCreate(groupId, artifactId); - artifact.setUpdatedAt(ZonedDateTime.now()); - return new Version().setVersion(version).setArtifact(artifact).setGroupId(groupId).setArtifactId(artifactId); - } - } - - public void persist(Version version) - { - versionRepo.persist(version); - eventRepo.persist(new Event().setAccountId(securityIdentity.getPrincipal().getName()).setType(EventType.UPLOAD).setResource(new Resource().setGroupId(version.getGroupId()).setArtifactId(version.getArtifactId()).setVersion(version.getVersion())).setTimestamp(ZonedDateTime.now())); - } -} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/context/ArtifactContext.java b/src/main/java/dev/dinauer/maven/maven/core/context/ArtifactContext.java new file mode 100644 index 0000000..e642344 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/context/ArtifactContext.java @@ -0,0 +1,39 @@ +package dev.dinauer.maven.maven.core.context; + +import dev.dinauer.maven.maven.shared.Extensions; + +public class ArtifactContext +{ + private final Extensions extensions; + private final String groupId; + private final String artifactId; + private final String filename; + + public ArtifactContext(Extensions extensions, String groupId, String artifactId, String filename) + { + this.extensions = extensions; + this.groupId = groupId; + this.artifactId = artifactId; + this.filename = filename; + } + + public Extensions extensions() + { + return extensions; + } + + public String groupId() + { + return groupId; + } + + public String artifactId() + { + return artifactId; + } + + public String filename() + { + return filename; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/context/ReleaseContext.java b/src/main/java/dev/dinauer/maven/maven/core/context/ReleaseContext.java new file mode 100644 index 0000000..22f09de --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/context/ReleaseContext.java @@ -0,0 +1,21 @@ +package dev.dinauer.maven.maven.core.context; + +import dev.dinauer.maven.maven.shared.Extensions; + +import java.util.Optional; + +public class ReleaseContext extends VersionContext +{ + private final String classifier; + + public ReleaseContext(Extensions extensions, String groupId, String artifactId, String filename, String version, String classifier) + { + super(extensions, groupId, artifactId, filename, version); + this.classifier = classifier; + } + + public Optional classifier() + { + return Optional.ofNullable(classifier); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/context/SnapshotContext.java b/src/main/java/dev/dinauer/maven/maven/core/context/SnapshotContext.java new file mode 100644 index 0000000..8d420bd --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/context/SnapshotContext.java @@ -0,0 +1,42 @@ +package dev.dinauer.maven.maven.core.context; + +import dev.dinauer.maven.maven.shared.Extensions; + +import java.util.Optional; + +public class SnapshotContext extends VersionContext +{ + private final String date; + private final String time; + private final int buildNumber; + private final String classifier; + + public SnapshotContext(Extensions extensions, String groupId, String artifactId, String filename, String version, String date, String time, int buildNumber, String classifier) + { + super(extensions, groupId, artifactId, filename, version); + this.date = date; + this.time = time; + this.buildNumber = buildNumber; + this.classifier = classifier; + } + + public String date() + { + return date; + } + + public String time() + { + return time; + } + + public int buildNumber() + { + return buildNumber; + } + + public Optional classifier() + { + return Optional.ofNullable(classifier); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/context/VersionContext.java b/src/main/java/dev/dinauer/maven/maven/core/context/VersionContext.java new file mode 100644 index 0000000..bccf98b --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/context/VersionContext.java @@ -0,0 +1,32 @@ +package dev.dinauer.maven.maven.core.context; + +import dev.dinauer.maven.maven.shared.Extensions; +import org.apache.commons.lang3.Strings; + +public class VersionContext extends ArtifactContext +{ + private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT"; + + private final String version; + + public VersionContext(Extensions extensions, String groupId, String artifactId, String filename, String version) + { + super(extensions, groupId, artifactId, filename); + this.version = version; + } + + public String version() + { + return version; + } + + public boolean isSnapshot() + { + return Strings.CI.endsWith(version, SNAPSHOT_SUFFIX); + } + + public String base() + { + return Strings.CI.removeEnd(version, SNAPSHOT_SUFFIX); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/model/ExtensionParser.java b/src/main/java/dev/dinauer/maven/maven/core/model/ExtensionParser.java index 5722b49..8844865 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/model/ExtensionParser.java +++ b/src/main/java/dev/dinauer/maven/maven/core/model/ExtensionParser.java @@ -1,22 +1,26 @@ package dev.dinauer.maven.maven.core.model; +import dev.dinauer.maven.maven.shared.Extensions; +import dev.dinauer.maven.maven.shared.Parser; +import dev.dinauer.maven.maven.shared.ParserResult; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.Strings; import java.util.List; +import java.util.Optional; -public class ExtensionParser +public class ExtensionParser implements Parser { private static final List FILE_TYPES = List.of("jar", "pom", "xml"); private static final List FILE_HASHES = List.of("md5", "sha1", "sha256", "sha512"); - public static Result parse(String raw) + public ParserResult parse(String raw) { String firstLevelExtension = FilenameUtils.getExtension(raw); String firstLevelBase = Strings.CI.removeEnd(raw, String.format(".%s", firstLevelExtension)); if (FILE_TYPES.contains(firstLevelExtension)) { - return new Result(firstLevelBase, FileExt.valueOf(firstLevelExtension.toUpperCase()), null); + return new ParserResult<>(firstLevelBase, new Extensions(FileExt.valueOf(firstLevelExtension.toUpperCase()), Optional.empty())); } if (FILE_HASHES.contains(firstLevelExtension)) { @@ -24,13 +28,9 @@ public class ExtensionParser if (FILE_TYPES.contains(secondLevelExtension)) { String secondLevelBase = Strings.CI.removeEnd(firstLevelBase, String.format(".%s", secondLevelExtension)); - return new Result(secondLevelBase, FileExt.valueOf(secondLevelExtension.toUpperCase()), FileHash.valueOf(firstLevelExtension.toUpperCase())); + return new ParserResult<>(secondLevelBase, new Extensions(FileExt.valueOf(secondLevelExtension.toUpperCase()), Optional.of(FileHash.valueOf(firstLevelExtension.toUpperCase())))); } } throw new RuntimeException(); } - - public record Result(String base, FileExt ext, FileHash hashExt) - { - } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java b/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java index adedc59..a0aca08 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java +++ b/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java @@ -1,5 +1,78 @@ package dev.dinauer.maven.maven.core.model; -public record MavenContext(String path, String groupId, String artifactId, Version version, File file) +import dev.dinauer.maven.maven.shared.Extensions; + +public class MavenContext { -} + private String path; + private String groupId; + private String artifactId; + private Version version; + private String filename; + private Extensions extensions; + + public MavenContext(String path, String groupId, String artifactId, Version version, String filename, Extensions extensions) + { + this.path = path; + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.filename = filename; + this.extensions = extensions; + } + + public String path() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public String groupId() + { + return groupId; + } + + public void setGroupId(String groupId) + { + this.groupId = groupId; + } + + public String artifactId() + { + return artifactId; + } + + public void setArtifactId(String artifactId) + { + this.artifactId = artifactId; + } + + public Version version() + { + return version; + } + + public void setVersion(Version version) + { + this.version = version; + } + + public String filename() + { + return filename; + } + + public void setFilename(String filename) + { + this.filename = filename; + } + + public Extensions extensions() + { + return extensions; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/model/SnapshotFileParser.java b/src/main/java/dev/dinauer/maven/maven/core/model/SnapshotFileParser.java deleted file mode 100644 index e25ca95..0000000 --- a/src/main/java/dev/dinauer/maven/maven/core/model/SnapshotFileParser.java +++ /dev/null @@ -1,80 +0,0 @@ -package dev.dinauer.maven.maven.core.model; - -import jakarta.ws.rs.BadRequestException; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.Strings; - -import java.util.List; -import java.util.OptionalInt; -import java.util.stream.IntStream; - -public class SnapshotFileParser -{ - public static SnapshotFile parse(String artifactId, String version, String raw) - { - ExtensionParser.Result extensionResult = ExtensionParser.parse(raw); - - SnapshotFile file = new SnapshotFile(); - - file.setBase(extensionResult.base()); - file.setType(extensionResult.ext()); - file.setHash(extensionResult.hashExt()); - - file.setRaw(raw); - file.setArtifactId(artifactId); - file.setVersion(version); - - String dataString = prepareForData(artifactId, version, raw); - file.setDate(getDate(dataString)); - - String timeString = prepareForTime(dataString); - file.setTime(getTime(timeString)); - - String buildNumberString = prepareForBuildNumber(timeString); - file.setBuildNumber(getBuildNumber(buildNumberString)); - - return file; - } - - private static String prepareForData(String artifact, String version, String raw) - { - return Strings.CI.removeStart(raw, String.format("%s-%s-", artifact, prepareVersion(version))); - } - - private static String prepareForTime(String path) - { - return Strings.CI.removeStart(path.substring(9), "."); - } - - private static String prepareForBuildNumber(String path) - { - return Strings.CI.removeStart(path.substring(7), "-"); - } - - private static int getBuildNumber(String path) - { - int nextDot = path.indexOf("."); - int nextDash = path.indexOf("-"); - OptionalInt optInt = IntStream.of(nextDash, nextDot).filter(index -> index > 0).min(); - if (optInt.isPresent()) - { - return Integer.parseInt(path.substring(0, optInt.getAsInt())); - } - throw new IllegalArgumentException(); - } - - private static String getDate(String path) - { - return path.substring(0, 8); - } - - private static String getTime(String path) - { - return path.substring(0, 6); - } - - private static String prepareVersion(String version) - { - return Strings.CI.removeEnd(version, "-SNAPSHOT"); - } -} diff --git a/src/main/java/dev/dinauer/maven/maven/core/model/Version.java b/src/main/java/dev/dinauer/maven/maven/core/model/Version.java index 14d67f8..f431f6f 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/model/Version.java +++ b/src/main/java/dev/dinauer/maven/maven/core/model/Version.java @@ -1,29 +1,40 @@ package dev.dinauer.maven.maven.core.model; +import org.apache.commons.lang3.Strings; + public class Version { - private String raw; - private Boolean isSnapshot; + private final String raw; + private final String base; + private final Boolean isSnapshot; + + public Version(String raw) + { + this.raw = raw; + if (Strings.CI.endsWith(raw, "-SNAPSHOT")) + { + this.base = Strings.CI.removeEnd(raw, "-SNAPSHOT"); + this.isSnapshot = true; + } + else + { + this.base = raw; + this.isSnapshot = false; + } + } public String getRaw() { return raw; } - public Version setRaw(String raw) + public String getBase() { - this.raw = raw; - return this; + return base; } - public Boolean getSnapshot() + public Boolean isSnapshot() { return isSnapshot; } - - public Version setSnapshot(Boolean snapshot) - { - isSnapshot = snapshot; - return this; - } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/parser/MavenUrlParser.java b/src/main/java/dev/dinauer/maven/maven/core/parser/MavenUrlParser.java index f031562..f2b0d60 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/parser/MavenUrlParser.java +++ b/src/main/java/dev/dinauer/maven/maven/core/parser/MavenUrlParser.java @@ -1,6 +1,7 @@ package dev.dinauer.maven.maven.core.parser; import dev.dinauer.maven.maven.core.model.Version; +import dev.dinauer.maven.maven.core.release.ReleaseVersion; import jakarta.ws.rs.BadRequestException; import java.util.List; @@ -32,11 +33,15 @@ public class MavenUrlParser return sections.get(sections.size() - 3); } - public Version version() + public String version() { List sections = getSections(path); - String raw = sections.get(sections.size() - 2); - return new Version().setRaw(raw).setSnapshot(raw.endsWith("-SNAPSHOT")); + return sections.get(sections.size() - 2); + } + + public String filename() + { + return getSections(path).getLast(); } private static List getSections(String path) diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/Jar.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJar.java similarity index 57% rename from src/main/java/dev/dinauer/maven/jpa/maven/Jar.java rename to src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJar.java index 71d9f8d..07c0b83 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/Jar.java +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJar.java @@ -1,12 +1,12 @@ -package dev.dinauer.maven.jpa.maven; +package dev.dinauer.maven.maven.core.release; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; @Entity -@Table(name = "jar") -public class Jar +@Table(name = "release_jar") +public class ReleaseJar { @Id @GeneratedValue(strategy = GenerationType.UUID) @@ -25,17 +25,19 @@ public class Jar private String filename; - @ManyToOne - @JoinColumn(name = "version_id") + private String classifier; + + @ManyToOne(cascade = CascadeType.PERSIST) + @JoinColumn(name = "release_version_id") @JsonBackReference - private Version version; + private ReleaseVersion releaseVersion; public String getId() { return id; } - public Jar setId(String id) + public ReleaseJar setId(String id) { this.id = id; return this; @@ -46,7 +48,7 @@ public class Jar return jar; } - public Jar setJar(byte[] jar) + public ReleaseJar setJar(byte[] jar) { this.jar = jar; return this; @@ -57,7 +59,7 @@ public class Jar return md5; } - public Jar setMd5(String md5) + public ReleaseJar setMd5(String md5) { this.md5 = md5; return this; @@ -68,20 +70,20 @@ public class Jar return sha1; } - public Jar setSha1(String sha1) + public ReleaseJar setSha1(String sha1) { this.sha1 = sha1; return this; } - public Version getVersion() + public ReleaseVersion getReleaseVersion() { - return version; + return releaseVersion; } - public Jar setVersion(Version version) + public ReleaseJar setReleaseVersion(ReleaseVersion releaseVersion) { - this.version = version; + this.releaseVersion = releaseVersion; return this; } @@ -90,7 +92,7 @@ public class Jar return url; } - public Jar setUrl(String url) + public ReleaseJar setUrl(String url) { this.url = url; return this; @@ -101,9 +103,20 @@ public class Jar return filename; } - public Jar setFilename(String filename) + public ReleaseJar setFilename(String filename) { this.filename = filename; return this; } + + public String getClassifier() + { + return classifier; + } + + public ReleaseJar setClassifier(String classifier) + { + this.classifier = classifier; + return this; + } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarRepo.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarRepo.java new file mode 100644 index 0000000..2c410e0 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarRepo.java @@ -0,0 +1,61 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.ArtifactService; +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; + +import java.util.Map; + +@ApplicationScoped +public class ReleaseJarRepo implements PanacheRepositoryBase +{ + @Inject + ReleaseVersionRepo releaseVersionRepo; + + public ReleaseJar find(ReleaseContext releaseContext) + { + ReleaseVersion version = releaseVersionRepo.findByGroupIdAndArtifactIdAndVersion(releaseContext.groupId(), releaseContext.artifactId(), releaseContext.version()); + if (version != null) + { + if (releaseContext.classifier().isPresent()) + { + return find("releaseVersion = :version AND classifier = :classifier", Map.ofEntries(Map.entry("version", version), Map.entry("classifier", releaseContext.classifier().get()))).firstResult(); + } + else + { + return find("releaseVersion = :version AND classifier IS NULL", Map.ofEntries(Map.entry("version", version))).firstResult(); + } + } + return null; + } + + public ReleaseJar require(ReleaseContext releaseContext) + { + ReleaseVersion version = releaseVersionRepo.requireByGroupIdAndArtifactIdAndVersion(releaseContext.groupId(), releaseContext.artifactId(), releaseContext.version()); + if (version != null) + { + if (releaseContext.classifier().isPresent()) + { + ReleaseJar releaseJar = find("releaseVersion = :version AND classifier = :classifier", Map.ofEntries(Map.entry("version", version), Map.entry("classifier", releaseContext.classifier().get()))).firstResult(); + if (releaseJar != null) + { + return releaseJar; + } + throw new NotFoundException(); + } + else + { + ReleaseJar releaseJar = find("releaseVersion = :version AND classifier IS NULL", Map.ofEntries(Map.entry("version", version))).firstResult(); + if (releaseJar != null) + { + return releaseJar; + } + throw new NotFoundException(); + } + } + return null; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarService.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarService.java new file mode 100644 index 0000000..2ebd716 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseJarService.java @@ -0,0 +1,73 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import dev.dinauer.maven.maven.core.context.VersionContext; +import dev.dinauer.maven.maven.core.model.MavenContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.NotImplementedException; + +import java.util.List; + +@ApplicationScoped +public class ReleaseJarService +{ + + @Inject + ReleaseJarRepo releaseJarRepo; + + @Inject + ReleaseVersionService releaseVersionService; + + public void store(ReleaseContext releaseContext, byte[] body) + { + ReleaseJar jar = releaseJarRepo.find(releaseContext); + if (jar == null) + { + create(releaseContext, body); + } + else + { + throw new WebApplicationException(409); + } + } + + public byte[] find(ReleaseContext releaseContext) + { + return releaseJarRepo.require(releaseContext).getJar(); + } + + public String findHash(ReleaseContext releaseContext) + { + switch (releaseContext.extensions().hashExt().orElseThrow()) + { + case SHA1 -> + { + return releaseJarRepo.require(releaseContext).getSha1(); + } + case MD5 -> + { + return releaseJarRepo.require(releaseContext).getMd5(); + } + } + throw new BadRequestException(); + } + + private void create(ReleaseContext releaseContext, byte[] content) + { + ReleaseJar releaseJar = new ReleaseJar(); + releaseJar.setReleaseVersion(releaseVersionService.findOrCreate(releaseContext)); + releaseJar.setJar(content); + releaseJar.setMd5(DigestUtils.md5Hex(content)); + releaseJar.setSha1(DigestUtils.sha1Hex(content)); + releaseJar.setClassifier(releaseContext.classifier().orElse(null)); + releaseJar.setFilename(releaseContext.filename()); + releaseJarRepo.persist(releaseJar); + } +} diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/Pom.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePom.java similarity index 66% rename from src/main/java/dev/dinauer/maven/jpa/maven/Pom.java rename to src/main/java/dev/dinauer/maven/maven/core/release/ReleasePom.java index 2bd299b..8f67e68 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/Pom.java +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePom.java @@ -1,12 +1,12 @@ -package dev.dinauer.maven.jpa.maven; +package dev.dinauer.maven.maven.core.release; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; @Entity -@Table(name = "pom") -public class Pom +@Table(name = "release_pom") +public class ReleasePom { @Id @GeneratedValue(strategy = GenerationType.UUID) @@ -26,16 +26,16 @@ public class Pom private String filename; @OneToOne - @JoinColumn(name = "version_id") + @JoinColumn(name = "release_version_id") @JsonBackReference - private Version version; + private ReleaseVersion releaseVersion; public String getId() { return id; } - public Pom setId(String id) + public ReleasePom setId(String id) { this.id = id; return this; @@ -46,7 +46,7 @@ public class Pom return pom; } - public Pom setPom(String pom) + public ReleasePom setPom(String pom) { this.pom = pom; return this; @@ -57,7 +57,7 @@ public class Pom return md5; } - public Pom setMd5(String md5) + public ReleasePom setMd5(String md5) { this.md5 = md5; return this; @@ -68,20 +68,20 @@ public class Pom return sha1; } - public Pom setSha1(String sha1) + public ReleasePom setSha1(String sha1) { this.sha1 = sha1; return this; } - public Version getVersion() + public ReleaseVersion getReleaseVersion() { - return version; + return releaseVersion; } - public Pom setVersion(Version version) + public ReleasePom setReleaseVersion(ReleaseVersion releaseVersion) { - this.version = version; + this.releaseVersion = releaseVersion; return this; } @@ -90,7 +90,7 @@ public class Pom return url; } - public Pom setUrl(String url) + public ReleasePom setUrl(String url) { this.url = url; return this; @@ -101,7 +101,7 @@ public class Pom return filename; } - public Pom setFilename(String filename) + public ReleasePom setFilename(String filename) { this.filename = filename; return this; diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomRepo.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomRepo.java new file mode 100644 index 0000000..3305df1 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomRepo.java @@ -0,0 +1,41 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; +import org.apache.commons.lang3.NotImplementedException; + +import java.util.Map; + +@ApplicationScoped +public class ReleasePomRepo implements PanacheRepositoryBase +{ + @Inject + ReleaseVersionRepo releaseVersionRepo; + + public ReleasePom find(ReleaseContext releaseContext) + { + ReleaseVersion version = releaseVersionRepo.findByGroupIdAndArtifactIdAndVersion(releaseContext.groupId(), releaseContext.artifactId(), releaseContext.version()); + if (version != null) + { + return find("releaseVersion = :version", Map.ofEntries(Map.entry("version", version))).firstResult(); + } + return null; + } + + public ReleasePom require(ReleaseContext releaseContext) + { + ReleaseVersion version = releaseVersionRepo.requireByGroupIdAndArtifactIdAndVersion(releaseContext.groupId(), releaseContext.artifactId(), releaseContext.version()); + ReleasePom releasePom = find("releaseVersion = :version", Map.ofEntries(Map.entry("version", version))).firstResult(); + if (releasePom != null) + { + return releasePom; + } + else + { + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomService.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomService.java new file mode 100644 index 0000000..f8c2c03 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleasePomService.java @@ -0,0 +1,62 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import dev.dinauer.maven.maven.core.model.FileHash; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.WebApplicationException; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.NotImplementedException; + +import java.nio.charset.StandardCharsets; + +@ApplicationScoped +public class ReleasePomService +{ + @Inject + ReleasePomRepo releasePomRepo; + + @Inject + ReleaseVersionService releaseVersionService; + + public void store(ReleaseContext releaseContext, byte[] body) + { + ReleasePom jar = releasePomRepo.find(releaseContext); + if (jar == null) + { + create(releaseContext, body); + } + else + { + throw new WebApplicationException(409); + } + } + + public String find(ReleaseContext releaseContext) + { + return releasePomRepo.require(releaseContext).getPom(); + } + + public String findHash(ReleaseContext releaseContext) + { + ReleasePom releasePom = releasePomRepo.require(releaseContext); + return switch (releaseContext.extensions().hashExt().orElseThrow()) + { + case MD5 -> releasePom.getMd5(); + case SHA1 -> releasePom.getSha1(); + default -> throw new IllegalStateException("Unexpected value: " + releaseContext.extensions().hashExt()); + }; + } + + private void create(ReleaseContext releaseContext, byte[] content) + { + ReleasePom releasePom = new ReleasePom(); + releasePom.setReleaseVersion(releaseVersionService.findOrCreate(releaseContext)); + releasePom.setPom(new String(content, StandardCharsets.UTF_8)); + releasePom.setMd5(DigestUtils.md5Hex(content)); + releasePom.setSha1(DigestUtils.sha1Hex(content)); + releasePom.setFilename(releaseContext.filename()); + releasePomRepo.persist(releasePom); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseService.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseService.java new file mode 100644 index 0000000..4af0cc6 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseService.java @@ -0,0 +1,59 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.*; +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.commons.lang3.NotImplementedException; + +@ApplicationScoped +public class ReleaseService +{ + @Inject + ReleaseJarService releaseJarService; + + @Inject + ReleasePomService releasePomService; + + @Transactional + public void upload(ReleaseContext releaseContext, byte[] body) + { + switch (releaseContext.extensions().ext()) + { + case JAR -> + { + if (releaseContext.extensions().hashExt().isEmpty()) + { + releaseJarService.store(releaseContext, body); + } + } + case POM -> + { + if (releaseContext.extensions().hashExt().isEmpty()) + { + releasePomService.store(releaseContext, body); + } + } + } + } + + public Response serve(ReleaseContext releaseContext) + { + switch (releaseContext.extensions().ext()) + { + case JAR -> + { + return Response.status(200).type(MediaType.APPLICATION_OCTET_STREAM).entity(releaseJarService.find(releaseContext)).build(); + } + case POM -> + { + return Response.status(200).type(MediaType.APPLICATION_XML).entity(releasePomService.find(releaseContext)).build(); + } + } + throw new BadRequestException(); + } +} diff --git a/src/main/java/dev/dinauer/maven/jpa/maven/Version.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersion.java similarity index 61% rename from src/main/java/dev/dinauer/maven/jpa/maven/Version.java rename to src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersion.java index 0ad96a2..454351b 100644 --- a/src/main/java/dev/dinauer/maven/jpa/maven/Version.java +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersion.java @@ -1,7 +1,9 @@ -package dev.dinauer.maven.jpa.maven; +package dev.dinauer.maven.maven.core.release; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; +import dev.dinauer.maven.maven.core.ArtifactId; +import dev.dinauer.maven.maven.core.Version; import dev.dinauer.maven.user.User; import jakarta.persistence.*; @@ -11,8 +13,8 @@ import java.util.List; import java.util.Optional; @Entity -@Table(name = "version") -public class Version +@Table(name = "release_version") +public class ReleaseVersion implements Version { @Id @GeneratedValue(strategy = GenerationType.UUID) @@ -31,13 +33,13 @@ public class Version @JsonBackReference private ArtifactId artifact; - @OneToMany(mappedBy = "version", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "releaseVersion", cascade = CascadeType.ALL) @JsonManagedReference - private List jars = new ArrayList<>(); + private List releaseJars = new ArrayList<>(); - @OneToOne(mappedBy = "version", cascade = CascadeType.ALL) + @OneToOne(mappedBy = "releaseVersion", cascade = CascadeType.ALL) @JsonManagedReference - private Pom pom; + private ReleasePom releasePom; @Column(name = "last_pulled") private ZonedDateTime lastPulled; @@ -56,7 +58,7 @@ public class Version return id; } - public Version setId(String id) + public ReleaseVersion setId(String id) { this.id = id; return this; @@ -67,7 +69,7 @@ public class Version return groupId; } - public Version setGroupId(String groupId) + public ReleaseVersion setGroupId(String groupId) { this.groupId = groupId; return this; @@ -78,7 +80,7 @@ public class Version return artifactId; } - public Version setArtifactId(String artifactId) + public ReleaseVersion setArtifactId(String artifactId) { this.artifactId = artifactId; return this; @@ -89,7 +91,7 @@ public class Version return version; } - public Version setVersion(String version) + public ReleaseVersion setVersion(String version) { this.version = version; return this; @@ -100,31 +102,31 @@ public class Version return artifact; } - public Version setArtifact(ArtifactId artifactId) + public ReleaseVersion setArtifact(ArtifactId artifactId) { this.artifact = artifactId; return this; } - public List getJars() + public List getJars() { - return jars; + return releaseJars; } - public Version setJars(List jars) + public ReleaseVersion setJars(List releaseJars) { - this.jars = jars; + this.releaseJars = releaseJars; return this; } - public Pom getPom() + public ReleasePom getPom() { - return pom; + return releasePom; } - public Version setPom(Pom pom) + public ReleaseVersion setPom(ReleasePom releasePom) { - this.pom = pom; + this.releasePom = releasePom; return this; } @@ -133,7 +135,7 @@ public class Version return lastPulled; } - public Version setLastPulled(ZonedDateTime lastPulled) + public ReleaseVersion setLastPulled(ZonedDateTime lastPulled) { this.lastPulled = lastPulled; return this; @@ -144,7 +146,7 @@ public class Version return uploadedBy; } - public Version setUploadedBy(String uploadedBy) + public ReleaseVersion setUploadedBy(String uploadedBy) { this.uploadedBy = uploadedBy; return this; @@ -155,7 +157,7 @@ public class Version return uploadUser; } - public Version setUploadAccount(User uploadUser) + public ReleaseVersion setUploadAccount(User uploadUser) { this.uploadUser = uploadUser; return this; @@ -166,7 +168,7 @@ public class Version return pullCount; } - public Version setPullCount(int pullCount) + public ReleaseVersion setPullCount(int pullCount) { this.pullCount = pullCount; return this; @@ -177,15 +179,21 @@ public class Version pullCount = pullCount + 1; } - public Optional getJarByFilename(String filename) + public Optional getJarByFilename(String filename) { - for (Jar jar : jars) + for (ReleaseJar releaseJar : releaseJars) { - if (jar.getFilename().equals(filename)) + if (releaseJar.getFilename().equals(filename)) { - return Optional.of(jar); + return Optional.of(releaseJar); } } return Optional.empty(); } + + @Override + public boolean isSnapshot() + { + return false; + } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionRepo.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionRepo.java new file mode 100644 index 0000000..2d1578a --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionRepo.java @@ -0,0 +1,29 @@ +package dev.dinauer.maven.maven.core.release; + +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.NotFoundException; + +import java.util.Map; + +@ApplicationScoped +public class ReleaseVersionRepo implements PanacheRepositoryBase +{ + public ReleaseVersion findByGroupIdAndArtifactIdAndVersion(String groupId, String artifactId, String version) + { + return find("version = :version AND artifact.artifactId = :artifactId AND artifact.group.groupId = :groupId", Map.ofEntries(Map.entry("groupId", groupId), Map.entry("artifactId", artifactId), Map.entry("version", version))).firstResult(); + } + + public ReleaseVersion requireByGroupIdAndArtifactIdAndVersion(String groupId, String artifactId, String version) + { + ReleaseVersion releaseVersion = find("version = :version AND artifact.artifactId = :artifactId AND artifact.group.groupId = :groupId", Map.ofEntries(Map.entry("groupId", groupId), Map.entry("artifactId", artifactId), Map.entry("version", version))).firstResult(); + if (releaseVersion != null) + { + return releaseVersion; + } + else + { + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionService.java b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionService.java new file mode 100644 index 0000000..1679249 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/ReleaseVersionService.java @@ -0,0 +1,33 @@ +package dev.dinauer.maven.maven.core.release; + +import dev.dinauer.maven.maven.core.ArtifactService; +import dev.dinauer.maven.maven.core.context.VersionContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class ReleaseVersionService +{ + @Inject + ReleaseVersionRepo releaseVersionRepo; + + @Inject + ArtifactService artifactService; + + public ReleaseVersion findOrCreate(VersionContext versionContext) + { + ReleaseVersion releaseVersion = releaseVersionRepo.findByGroupIdAndArtifactIdAndVersion(versionContext.groupId(), versionContext.artifactId(), versionContext.version()); + if (releaseVersion != null) + { + return releaseVersion; + } + else + { + ReleaseVersion created = new ReleaseVersion(); + created.setArtifact(artifactService.findOrCreate(versionContext.groupId(), versionContext.artifactId())); + created.setVersion(versionContext.version()); + releaseVersionRepo.persist(created); + return created; + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFile.java b/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFile.java new file mode 100644 index 0000000..a5d5575 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFile.java @@ -0,0 +1,17 @@ +package dev.dinauer.maven.maven.core.release.parser; + +public class ReleaseFile +{ + private String classifier; + + public ReleaseFile setClassifier(String classifier) + { + this.classifier = classifier; + return this; + } + + public String getClassifier() + { + return classifier; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFileParser.java b/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFileParser.java new file mode 100644 index 0000000..63f2495 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/release/parser/ReleaseFileParser.java @@ -0,0 +1,38 @@ +package dev.dinauer.maven.maven.core.release.parser; + +import dev.dinauer.maven.maven.shared.Parser; +import dev.dinauer.maven.maven.shared.ParserResult; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Strings; + +public class ReleaseFileParser implements Parser +{ + private final String artifactId; + private final String version; + + public ReleaseFileParser(String artifactId, String version) + { + this.version = version; + this.artifactId = artifactId; + } + + @Override + public ParserResult parse(String input) + { + String withoutGroupAndArtifact = dropArtifactIdAndVersion(input); + if (StringUtils.isBlank(withoutGroupAndArtifact)) + { + return new ParserResult<>(null, new ReleaseFile()); + } + return new ParserResult<>(null, new ReleaseFile().setClassifier(withoutGroupAndArtifact)); + } + + private String dropArtifactIdAndVersion(String input) + { + if (input.equals(String.format("%s-%s", artifactId, version))) + { + return ""; + } + return Strings.CI.removeStart(input, String.format("%s-%s-", artifactId, version)); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/Resource.java b/src/main/java/dev/dinauer/maven/maven/core/rest/Resource.java similarity index 52% rename from src/main/java/dev/dinauer/maven/maven/core/Resource.java rename to src/main/java/dev/dinauer/maven/maven/core/rest/Resource.java index 9e8df41..214f327 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/Resource.java +++ b/src/main/java/dev/dinauer/maven/maven/core/rest/Resource.java @@ -1,6 +1,8 @@ -package dev.dinauer.maven.maven.core; +package dev.dinauer.maven.maven.core.rest; import com.fasterxml.jackson.core.JsonProcessingException; +import dev.dinauer.maven.maven.core.MavenService; +import dev.dinauer.maven.maven.core.release.ReleaseService; import io.quarkus.security.Authenticated; import jakarta.inject.Inject; import jakarta.ws.rs.*; @@ -12,19 +14,22 @@ import jakarta.ws.rs.core.Response; public class Resource { @Inject - Service service; + ReleaseService releaseService; + + @Inject + MavenService mavenService; @PUT @Path("/{path: .*}") - public Response put(@PathParam("path") String path, byte[] body) + public void put(@PathParam("path") String path, byte[] body) throws JsonProcessingException { - return service.upload(path, body); + mavenService.upload(path, body); } @GET @Path("/{path: .*}") public Response get(@PathParam("path") String path) throws JsonProcessingException { - return service.serve(path); + return mavenService.serve(path); } } diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundle.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundle.java new file mode 100644 index 0000000..ac9d897 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundle.java @@ -0,0 +1,110 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.*; + +import java.util.List; + +@Entity +@Table(name = "snapshot_bundle") +public class SnapshotBundle +{ + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + private String date; + + private String time; + + @Column(name = "build_number") + private int buildNumber; + + @ManyToOne(cascade = CascadeType.PERSIST) + @JoinColumn(name = "snapshot_version_id") + @JsonBackReference + private SnapshotVersion snapshotVersion; + + @OneToMany(mappedBy = "snapshotBundle") + private List jars; + + @OneToOne(mappedBy = "snapshotBundle") + private SnapshotPom pom; + + public String getId() + { + return id; + } + + public SnapshotBundle setId(String id) + { + this.id = id; + return this; + } + + public String getDate() + { + return date; + } + + public SnapshotBundle setDate(String date) + { + this.date = date; + return this; + } + + public String getTime() + { + return time; + } + + public SnapshotBundle setTime(String time) + { + this.time = time; + return this; + } + + public int getBuildNumber() + { + return buildNumber; + } + + public SnapshotBundle setBuildNumber(int buildNumber) + { + this.buildNumber = buildNumber; + return this; + } + + public SnapshotVersion getSnapshotVersion() + { + return snapshotVersion; + } + + public SnapshotBundle setSnapshotVersion(SnapshotVersion snapshotVersion) + { + this.snapshotVersion = snapshotVersion; + return this; + } + + public List getJars() + { + return jars; + } + + public SnapshotBundle setJars(List jars) + { + this.jars = jars; + return this; + } + + public SnapshotPom getPom() + { + return pom; + } + + public SnapshotBundle setPom(SnapshotPom pom) + { + this.pom = pom; + return this; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleRepo.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleRepo.java new file mode 100644 index 0000000..9107b9a --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleRepo.java @@ -0,0 +1,15 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; + +import java.util.Map; + +@ApplicationScoped +public class SnapshotBundleRepo implements PanacheRepositoryBase +{ + public SnapshotBundle findByVersionAndProperties(SnapshotVersion version, String date, String time, int buildNumber) + { + return find("snapshotVersion = :snapshotVersion AND date = :date AND time = :time AND buildNumber = :buildNumber", Map.ofEntries(Map.entry("snapshotVersion", version), Map.entry("date", date), Map.entry("time", time), Map.entry("buildNumber", buildNumber))).firstResult(); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleService.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleService.java new file mode 100644 index 0000000..e5b51cf --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotBundleService.java @@ -0,0 +1,50 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; + +@ApplicationScoped +public class SnapshotBundleService +{ + @Inject + SnapshotBundleRepo snapshotBundleRepo; + + @Inject + SnapshotVersionService snapshotVersionService; + + public SnapshotBundle findOrCreate(SnapshotContext snapshotContext) + { + SnapshotVersion snapshotVersion = snapshotVersionService.findOrCreate(snapshotContext); + SnapshotBundle snapshotBundle = snapshotBundleRepo.findByVersionAndProperties(snapshotVersion, snapshotContext.date(), snapshotContext.time(), snapshotContext.buildNumber()); + if (snapshotBundle != null) + { + return snapshotBundle; + } + else + { + SnapshotBundle created = new SnapshotBundle(); + created.setDate(snapshotContext.date()); + created.setTime(snapshotContext.time()); + created.setBuildNumber(snapshotContext.buildNumber()); + created.setSnapshotVersion(snapshotVersion); + snapshotBundleRepo.persist(created); + return created; + } + } + + public SnapshotBundle require(SnapshotContext snapshotContext) + { + SnapshotVersion snapshotVersion = snapshotVersionService.require(snapshotContext); + SnapshotBundle snapshotBundle = snapshotBundleRepo.findByVersionAndProperties(snapshotVersion, snapshotContext.date(), snapshotContext.time(), snapshotContext.buildNumber()); + if (snapshotBundle != null) + { + return snapshotBundle; + } + else + { + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotFile.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotFile.java new file mode 100644 index 0000000..9d7a71f --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotFile.java @@ -0,0 +1,53 @@ +package dev.dinauer.maven.maven.core.snapshot; + +public class SnapshotFile +{ + private String date; + private String time; + private int buildNumber; + private String classifier; + + public String getDate() + { + return date; + } + + public SnapshotFile setDate(String date) + { + this.date = date; + return this; + } + + public String getTime() + { + return time; + } + + public SnapshotFile setTime(String time) + { + this.time = time; + return this; + } + + public int getBuildNumber() + { + return buildNumber; + } + + public SnapshotFile setBuildNumber(int buildNumber) + { + this.buildNumber = buildNumber; + return this; + } + + public String getClassifier() + { + return classifier; + } + + public SnapshotFile setClassifier(String classifier) + { + this.classifier = classifier; + return this; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJar.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJar.java new file mode 100644 index 0000000..2691fc6 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJar.java @@ -0,0 +1,91 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import jakarta.persistence.*; + +@Entity +@Table(name = "snapshot_jar") +public class SnapshotJar +{ + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + private String md5; + + private String sha1; + + @Column(columnDefinition = "bytea") + private byte[] jar; + + private String classifier; + + @ManyToOne(cascade = CascadeType.PERSIST) + @JoinColumn(name = "snapshot_bundle_id") + private SnapshotBundle snapshotBundle; + + public String getId() + { + return id; + } + + public SnapshotJar setId(String id) + { + this.id = id; + return this; + } + + public String getMd5() + { + return md5; + } + + public SnapshotJar setMd5(String md5) + { + this.md5 = md5; + return this; + } + + public String getSha1() + { + return sha1; + } + + public SnapshotJar setSha1(String sha1) + { + this.sha1 = sha1; + return this; + } + + public byte[] getJar() + { + return jar; + } + + public SnapshotJar setJar(byte[] jar) + { + this.jar = jar; + return this; + } + + public String getClassifier() + { + return classifier; + } + + public SnapshotJar setClassifier(String classifier) + { + this.classifier = classifier; + return this; + } + + public SnapshotBundle getSnapshotBundle() + { + return snapshotBundle; + } + + public SnapshotJar setSnapshotBundle(SnapshotBundle snapshotBundle) + { + this.snapshotBundle = snapshotBundle; + return this; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarRepo.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarRepo.java new file mode 100644 index 0000000..14a88cc --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarRepo.java @@ -0,0 +1,52 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; + +import java.util.Map; + +@ApplicationScoped +public class SnapshotJarRepo implements PanacheRepositoryBase +{ + @Inject + SnapshotBundleService snapshotBundleService; + + public SnapshotJar find(SnapshotContext snapshotContext) + { + SnapshotBundle bundle = snapshotBundleService.findOrCreate(snapshotContext); + if (snapshotContext.classifier().isPresent()) + { + return find("snapshotBundle = :snapshotBundle AND classifier = :classifier", Map.ofEntries(Map.entry("snapshotBundle", bundle), Map.entry("classifier", snapshotContext.classifier().get()))).firstResult(); + } + else + { + return find("snapshotBundle = :snapshotBundle AND classifier IS NULL", Map.ofEntries(Map.entry("snapshotBundle", bundle))).firstResult(); + } + } + + public SnapshotJar require(SnapshotContext snapshotContext) + { + SnapshotBundle bundle = snapshotBundleService.require(snapshotContext); + if (snapshotContext.classifier().isPresent()) + { + SnapshotJar snapshotJar = find("snapshotBundle = :snapshotBundle AND classifier = :classifier", Map.ofEntries(Map.entry("snapshotBundle", bundle), Map.entry("classifier", snapshotContext.classifier().get()))).firstResult(); + if (snapshotJar != null) + { + return snapshotJar; + } + throw new NotFoundException(); + } + else + { + SnapshotJar snapshotJar = find("snapshotBundle = :snapshotBundle AND classifier IS NULL", Map.ofEntries(Map.entry("snapshotBundle", bundle))).firstResult(); + if (snapshotJar != null) + { + return snapshotJar; + } + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarService.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarService.java new file mode 100644 index 0000000..a606b05 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotJarService.java @@ -0,0 +1,64 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.WebApplicationException; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.NotImplementedException; + +@ApplicationScoped +public class SnapshotJarService +{ + @Inject + SnapshotBundleService snapshotBundleService; + + @Inject + SnapshotJarRepo snapshotJarRepo; + + public void store(SnapshotContext snapshotContext, byte[] body) + { + SnapshotJar snapshotJar = snapshotJarRepo.find(snapshotContext); + if (snapshotJar == null) + { + create(snapshotContext, body); + } + else + { + throw new WebApplicationException(501); + } + } + + public byte[] find(SnapshotContext snapshotContext) + { + return snapshotJarRepo.require(snapshotContext).getJar(); + } + + public String findHash(SnapshotContext snapshotContext) + { + switch (snapshotContext.extensions().hashExt().orElseThrow()) + { + case SHA1 -> + { + return snapshotJarRepo.require(snapshotContext).getSha1(); + } + case MD5 -> + { + return snapshotJarRepo.require(snapshotContext).getMd5(); + } + } + throw new BadRequestException(); + } + + private void create(SnapshotContext snapshotContext, byte[] content) + { + SnapshotJar snapshotJar = new SnapshotJar(); + snapshotJar.setSnapshotBundle(snapshotBundleService.findOrCreate(snapshotContext)); + snapshotJar.setJar(content); + snapshotJar.setMd5(DigestUtils.md5Hex(content)); + snapshotJar.setSha1(DigestUtils.sha1Hex(content)); + snapshotJar.setClassifier(snapshotContext.classifier().orElse(null)); + snapshotJarRepo.persist(snapshotJar); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPom.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPom.java new file mode 100644 index 0000000..bc2b251 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPom.java @@ -0,0 +1,81 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.*; + +@Entity +@Table(name = "snapshot_pom") +public class SnapshotPom +{ + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + private String md5; + + private String sha1; + + @JsonIgnore + @Column(columnDefinition = "TEXT") + @Basic(fetch = FetchType.LAZY) + private String pom; + + @OneToOne(cascade = CascadeType.PERSIST) + @JoinColumn(name = "snapshot_bundle_id") + private SnapshotBundle snapshotBundle; + + public String getId() + { + return id; + } + + public SnapshotPom setId(String id) + { + this.id = id; + return this; + } + + public String getMd5() + { + return md5; + } + + public SnapshotPom setMd5(String md5) + { + this.md5 = md5; + return this; + } + + public String getSha1() + { + return sha1; + } + + public SnapshotPom setSha1(String sha1) + { + this.sha1 = sha1; + return this; + } + + public String getPom() + { + return pom; + } + + public SnapshotPom setPom(String pom) + { + this.pom = pom; + return this; + } + + public SnapshotBundle getSnapshotBundle() + { + return snapshotBundle; + } + + public SnapshotPom setSnapshotBundle(SnapshotBundle snapshotBundle) + { + this.snapshotBundle = snapshotBundle; + return this; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomRepo.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomRepo.java new file mode 100644 index 0000000..594790d --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomRepo.java @@ -0,0 +1,31 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.release.ReleasePom; +import dev.dinauer.maven.maven.core.release.ReleaseVersion; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.NotFoundException; + +import java.util.Map; + +@ApplicationScoped +public class SnapshotPomRepo implements PanacheRepositoryBase +{ + public SnapshotPom find(SnapshotBundle bundle) + { + return find("snapshotBundle = :snapshotBundle", Map.ofEntries(Map.entry("snapshotBundle", bundle))).firstResult(); + } + + public SnapshotPom require(SnapshotBundle bundle) + { + SnapshotPom snapshotPom = find("snapshotBundle = :bundle", Map.ofEntries(Map.entry("bundle", bundle))).firstResult(); + if (snapshotPom != null) + { + return snapshotPom; + } + else + { + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomService.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomService.java new file mode 100644 index 0000000..5bf18ed --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotPomService.java @@ -0,0 +1,62 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.WebApplicationException; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.NotImplementedException; + +import java.nio.charset.StandardCharsets; + +@ApplicationScoped +public class SnapshotPomService +{ + @Inject + SnapshotPomRepo snapshotPomRepo; + + @Inject + SnapshotBundleService snapshotBundleService; + + public void store(SnapshotContext snapshotContext, byte[] body) + { + SnapshotBundle snapshotBundle = snapshotBundleService.findOrCreate(snapshotContext); + SnapshotPom snapshotPom = snapshotPomRepo.find(snapshotBundle); + if (snapshotPom == null) + { + create(snapshotBundle, body); + } + else + { + throw new WebApplicationException(501); + } + } + + public String find(SnapshotContext snapshotContext) + { + SnapshotBundle snapshotBundle = snapshotBundleService.require(snapshotContext); + return snapshotPomRepo.require(snapshotBundle).getPom(); + } + + public String findHash(SnapshotContext snapshotContext) + { + SnapshotBundle snapshotBundle = snapshotBundleService.require(snapshotContext); + SnapshotPom snapshotPom = snapshotPomRepo.require(snapshotBundle); + return switch (snapshotContext.extensions().hashExt().orElseThrow()) + { + case MD5 -> snapshotPom.getMd5(); + case SHA1 -> snapshotPom.getSha1(); + default -> throw new IllegalStateException("Unexpected value: " + snapshotContext.extensions().hashExt()); + }; + } + + private void create(SnapshotBundle bundle, byte[] content) + { + SnapshotPom snapshotPom = new SnapshotPom(); + snapshotPom.setSnapshotBundle(bundle); + snapshotPom.setPom(new String(content, StandardCharsets.UTF_8)); + snapshotPom.setMd5(DigestUtils.md5Hex(content)); + snapshotPom.setSha1(DigestUtils.sha1Hex(content)); + snapshotPomRepo.persist(snapshotPom); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotService.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotService.java new file mode 100644 index 0000000..99c477f --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotService.java @@ -0,0 +1,52 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.context.ReleaseContext; +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +@ApplicationScoped +public class SnapshotService +{ + @Inject + SnapshotPomService snapshotPomService; + + @Inject + SnapshotJarService snapshotJarService; + + @Transactional + public void upload(SnapshotContext snapshotContext, byte[] content) + { + switch (snapshotContext.extensions().ext()) + { + case JAR -> + { + snapshotJarService.store(snapshotContext, content); + } + case POM -> + { + snapshotPomService.store(snapshotContext, content); + } + } + } + + public Response serve(SnapshotContext snapshotContext) + { + switch (snapshotContext.extensions().ext()) + { + case JAR -> + { + return Response.status(200).type(MediaType.APPLICATION_OCTET_STREAM).entity(snapshotJarService.find(snapshotContext)).build(); + } + case POM -> + { + return Response.status(200).type(MediaType.APPLICATION_XML).entity(snapshotPomService.find(snapshotContext)).build(); + } + } + throw new BadRequestException(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersion.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersion.java new file mode 100644 index 0000000..ce3e136 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersion.java @@ -0,0 +1,79 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import dev.dinauer.maven.maven.core.ArtifactId; +import dev.dinauer.maven.maven.core.Version; +import jakarta.persistence.*; + +import java.util.List; + +@Entity +@Table(name = "snapshot_version") +public class SnapshotVersion implements Version +{ + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + private String version; + + @ManyToOne(cascade = CascadeType.PERSIST) + @JoinColumn(name = "artifact_id") + @JsonBackReference + private ArtifactId artifact; + + @OneToMany(mappedBy = "snapshotVersion") + @JsonManagedReference + private List snapshotBundles; + + public String getId() + { + return id; + } + + public SnapshotVersion setId(String id) + { + this.id = id; + return this; + } + + public String getVersion() + { + return version; + } + + public SnapshotVersion setVersion(String version) + { + this.version = version; + return this; + } + + public ArtifactId getArtifact() + { + return artifact; + } + + public SnapshotVersion setArtifact(ArtifactId artifact) + { + this.artifact = artifact; + return this; + } + + public List getSnapshotBundles() + { + return snapshotBundles; + } + + public SnapshotVersion setSnapshotBundles(List snapshotBundles) + { + this.snapshotBundles = snapshotBundles; + return this; + } + + @Override + public boolean isSnapshot() + { + return true; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionRepo.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionRepo.java new file mode 100644 index 0000000..46d68c2 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionRepo.java @@ -0,0 +1,16 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.ArtifactId; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; + +import java.util.Map; + +@ApplicationScoped +public class SnapshotVersionRepo implements PanacheRepositoryBase +{ + public SnapshotVersion findByArtifactAndVersion(ArtifactId artifactId, String version) + { + return find("artifact = :artifact AND version = :version", Map.ofEntries(Map.entry("artifact", artifactId), Map.entry("version", version))).firstResult(); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionService.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionService.java new file mode 100644 index 0000000..350851f --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/SnapshotVersionService.java @@ -0,0 +1,51 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import dev.dinauer.maven.maven.core.ArtifactId; +import dev.dinauer.maven.maven.core.ArtifactService; +import dev.dinauer.maven.maven.core.context.SnapshotContext; +import dev.dinauer.maven.maven.core.context.VersionContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; + +@ApplicationScoped +public class SnapshotVersionService +{ + @Inject + ArtifactService artifactService; + + @Inject + SnapshotVersionRepo snapshotVersionRepo; + + public SnapshotVersion findOrCreate(VersionContext versionContext) + { + ArtifactId artifactId = artifactService.findOrCreate(versionContext.groupId(), versionContext.artifactId()); + SnapshotVersion snapshotVersion = snapshotVersionRepo.findByArtifactAndVersion(artifactId, versionContext.version()); + if (snapshotVersion != null) + { + return snapshotVersion; + } + else + { + SnapshotVersion created = new SnapshotVersion(); + created.setArtifact(artifactId); + created.setVersion(versionContext.version()); + snapshotVersionRepo.persist(created); + return created; + } + } + + public SnapshotVersion require(VersionContext versionContext) + { + ArtifactId artifactId = artifactService.require(versionContext.groupId(), versionContext.artifactId()); + SnapshotVersion snapshotVersion = snapshotVersionRepo.findByArtifactAndVersion(artifactId, versionContext.version()); + if (snapshotVersion != null) + { + return snapshotVersion; + } + else + { + throw new NotFoundException(); + } + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParser.java b/src/main/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParser.java new file mode 100644 index 0000000..9a63586 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParser.java @@ -0,0 +1,50 @@ +package dev.dinauer.maven.maven.core.snapshot.parser; + +import dev.dinauer.maven.maven.core.snapshot.SnapshotFile; +import dev.dinauer.maven.maven.shared.Parser; +import dev.dinauer.maven.maven.shared.ParserResult; +import org.apache.commons.lang3.Strings; + +import java.util.List; + +public class SnapshotFileParser implements Parser +{ + private final String groupId; + private final String artifactId; + + public SnapshotFileParser(String groupId, String artifactId) + { + this.groupId = groupId; + this.artifactId = artifactId; + } + + @Override + public ParserResult parse(String input) + { + String withoutGroupAndArtifact = dropGroupAndArtifact(input); + String[] sections = withoutGroupAndArtifact.split("-"); + if (sections.length >= 2) + { + String[] dateTime = sections[0].split("\\."); + if (dateTime.length == 2) + { + SnapshotFile file = new SnapshotFile(); + file.setDate(dateTime[0]); + file.setTime(dateTime[1]); + file.setBuildNumber(Integer.parseInt(sections[1])); + if (sections.length >= 3) + { + String classifier = String.join("-", List.of(sections).subList(2, sections.length)); + file.setClassifier(classifier); + } + return new ParserResult<>(null, file); + } + } + throw new IllegalArgumentException(); + } + + private String dropGroupAndArtifact(String input) + { + return Strings.CI.removeStart(input, String.format("%s-%s-", groupId, artifactId)); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/shared/Extensions.java b/src/main/java/dev/dinauer/maven/maven/shared/Extensions.java new file mode 100644 index 0000000..550b6c4 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/shared/Extensions.java @@ -0,0 +1,10 @@ +package dev.dinauer.maven.maven.shared; + +import dev.dinauer.maven.maven.core.model.FileExt; +import dev.dinauer.maven.maven.core.model.FileHash; + +import java.util.Optional; + +public record Extensions(FileExt ext, Optional hashExt) +{ +} diff --git a/src/main/java/dev/dinauer/maven/maven/shared/GenericFile.java b/src/main/java/dev/dinauer/maven/maven/shared/GenericFile.java new file mode 100644 index 0000000..c7fb5c7 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/shared/GenericFile.java @@ -0,0 +1,5 @@ +package dev.dinauer.maven.maven.shared; + +public record GenericFile

(Extensions extensions, P details) +{ +} \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/shared/MavenCoordinates.java b/src/main/java/dev/dinauer/maven/maven/shared/MavenCoordinates.java new file mode 100644 index 0000000..860b96d --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/shared/MavenCoordinates.java @@ -0,0 +1,5 @@ +package dev.dinauer.maven.maven.shared; + +public record MavenCoordinates(String groupId, String artifactId, String version) +{ +} diff --git a/src/main/java/dev/dinauer/maven/maven/shared/Parser.java b/src/main/java/dev/dinauer/maven/maven/shared/Parser.java new file mode 100644 index 0000000..3d1605e --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/shared/Parser.java @@ -0,0 +1,6 @@ +package dev.dinauer.maven.maven.shared; + +public interface Parser

+{ + ParserResult

parse(String input); +} diff --git a/src/main/java/dev/dinauer/maven/maven/shared/ParserResult.java b/src/main/java/dev/dinauer/maven/maven/shared/ParserResult.java new file mode 100644 index 0000000..49ce5c8 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/shared/ParserResult.java @@ -0,0 +1,5 @@ +package dev.dinauer.maven.maven.shared; + +public record ParserResult

(String remainder, P result) +{ +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d03785d..aee3520 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,6 +5,7 @@ %dev.quarkus.http.cors.access-control-allow-credentials=true quarkus.http.access-log.enabled=true +# HTTP Test %test.quarkus.http.test-port=9081 # Auth @@ -12,19 +13,22 @@ quarkus.http.auth.permission.authenticated.paths=/* quarkus.http.auth.permission.authenticated.policy=authenticated # Postgres +quarkus.hibernate-orm.schema-management.strategy=validate quarkus.datasource.db-kind=postgresql -%dev.quarkus.datasource.username=postgres -%dev.quarkus.datasource.password=postgres -%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres +%dev,test.quarkus.datasource.username=postgres +%dev,test.quarkus.datasource.password=postgres +%dev,test.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres +# Flyway +%dev,test.quarkus.flyway.clean-at-start=true +quarkus.flyway.migrate-at-start=true + +# OIDC Server quarkus.oidc.auth-server-url=http://localhost:8089/api/realms/maven quarkus.oidc.client-id=backend - quarkus.oidc-client.auth-server-url=http://localhost:8089/api/realms/maven quarkus.oidc-client.client-id=backend quarkus.oidc-client.credentials.secret=backend -quarkus.rest-client.idp.url=http://localhost:8089/api/realms/maven - -%dev,test.quarkus.flyway.clean-at-start=true -quarkus.flyway.migrate-at-start=true \ No newline at end of file +# OIDC REST +quarkus.rest-client.idp.url=http://localhost:8089/api/realms/maven \ No newline at end of file diff --git a/src/main/resources/db/migration/V1.0.0__init.sql b/src/main/resources/db/migration/V1.0.0__init.sql index f9c9d82..3f46847 100644 --- a/src/main/resources/db/migration/V1.0.0__init.sql +++ b/src/main/resources/db/migration/V1.0.0__init.sql @@ -2,100 +2,163 @@ create table group_id ( created_at timestamp(6) with time zone, updated_at timestamp(6) with time zone, - group_id varchar(255), - id varchar(255) not null - primary key + group_id varchar(255), + id varchar(255) not null + constraint group_id_pkey + primary key ); create table artifact_id ( - created_at timestamp(6) with time zone, - updated_at timestamp(6) with time zone, - artifact_id varchar(255), - group_id varchar(255) + created_at timestamp(6) with time zone, + updated_at timestamp(6) with time zone, + artifact_id varchar(255), + group_id varchar(255) constraint fkghhaxmc9rw9lhck83y9o6bp1o references group_id, group_id_long varchar(255), - id varchar(255) not null - primary key + id varchar(255) not null + constraint artifact_id_pkey + primary key +); + +create table release_version +( + pull_count integer, + last_pulled timestamp(6) with time zone, + artifact_id varchar(255) + constraint fk7c5hahrl7ws76sidh9d1434b8 + references artifact_id, + artifact_id_long varchar(255), + group_id_long varchar(255), + id varchar(255) not null + constraint release_version_pkey + primary key, + uploaded_by varchar(255), + version varchar(255) +); + +create table release_jar +( + classifier varchar(255), + filename varchar(255), + id varchar(255) not null + constraint release_jar_pkey + primary key, + md5 varchar(255), + release_version_id varchar(255) + constraint fkfbi277pdpmkulym55pq12eg0g + references release_version, + sha1 varchar(255), + url varchar(255), + jar bytea +); + +create table release_pom +( + filename varchar(255), + id varchar(255) not null + constraint release_pom_pkey + primary key, + md5 varchar(255), + pom text, + release_version_id varchar(255) + constraint release_pom_release_version_id_key + unique + constraint fk3ojqytildpdfl7q3lf5xri1c6 + references release_version, + sha1 varchar(255), + url varchar(255) ); create table resource ( artifact_id varchar(255), - group_id varchar(255), - id varchar(255) not null - primary key, - version varchar(255) + group_id varchar(255), + id varchar(255) not null + constraint resource_pkey + primary key, + version varchar(255) ); create table event ( - timestamp timestamp(6) with time zone, - accountid varchar(255), - id varchar(255) not null - primary key, + timestamp timestamp(6) with time zone, + accountid varchar(255), + id varchar(255) not null + constraint event_pkey + primary key, resource_id varchar(255) - unique + constraint event_resource_id_key + unique constraint fkclx5xnhdf2y3l1g3ae6ygsjmf references resource, - type varchar(255) + type varchar(255) constraint event_type_check - check ((type)::text = ANY ((ARRAY ['UPLOAD'::character varying, 'DELETE'::character varying])::text[])) + check ((type)::text = ANY ((ARRAY['UPLOAD'::character varying, 'DELETE'::character varying])::text[])) + ); + +create table snapshot_version +( + artifact_id varchar(255) + constraint fk64mje366563n82s8hy9bkfr14 + references artifact_id, + id varchar(255) not null + constraint snapshot_version_pkey + primary key, + version varchar(255) +); + +create table snapshot_bundle +( + build_number integer, + date varchar(255), + id varchar(255) not null + constraint snapshot_bundle_pkey + primary key, + snapshot_version_id varchar(255) + constraint fk3ve4wtmuywedyrri24dnqrpd9 + references snapshot_version, + time varchar(255) +); + +create table snapshot_jar +( + classifier varchar(255), + id varchar(255) not null + constraint snapshot_jar_pkey + primary key, + md5 varchar(255), + sha1 varchar(255), + snapshot_bundle_id varchar(255) + constraint fkp2vmi4ih595cbhnwiq6q1yb2n + references snapshot_bundle, + jar bytea +); + +create table snapshot_pom +( + id varchar(255) not null + constraint snapshot_pom_pkey + primary key, + md5 varchar(255), + pom text, + sha1 varchar(255), + snapshot_bundle_id varchar(255) + constraint snapshot_pom_snapshot_bundle_id_key + unique + constraint fkr9gdl40j7x0ch6raju9gitfr1 + references snapshot_bundle ); create table token ( expires_at date, created_at timestamp(6) with time zone, - id varchar(255) not null - primary key, - name varchar(255), - token varchar(255), - user_id varchar(255) -); - -create table version -( - pull_count integer, - last_pulled timestamp(6) with time zone, - artifact_id varchar(255) - constraint fklcnjnhvigubmjqng9wt7lcw71 - references artifact_id, - artifact_id_long varchar(255), - group_id_long varchar(255), - id varchar(255) not null - primary key, - uploaded_by varchar(255), - version varchar(255) -); - -create table jar -( - filename varchar(255), - id varchar(255) not null - primary key, - md5 varchar(255), - sha1 varchar(255), - url varchar(255), - version_id varchar(255) - constraint fkaf1ctqgugsre652w5465uhjbu - references version, - jar bytea -); - -create table pom -( - filename varchar(255), - id varchar(255) not null - primary key, - md5 varchar(255), - pom text, - sha1 varchar(255), - url varchar(255), - version_id varchar(255) - unique - constraint fker1jyb1nf0vpmyv5b6ooydplu - references version -); - + id varchar(255) not null + constraint token_pkey + primary key, + name varchar(255), + token varchar(255), + user_id varchar(255) +); \ No newline at end of file diff --git a/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java b/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java index 93abebb..c2bdec1 100644 --- a/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java +++ b/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java @@ -1,6 +1,6 @@ package dev.dinauer.maven.maven.core; -import dev.dinauer.maven.jpa.maven.Version; +import dev.dinauer.maven.maven.core.release.ReleaseVersion; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.security.TestSecurity; import io.restassured.RestAssured; @@ -10,7 +10,9 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Optional; @QuarkusTest @@ -19,32 +21,54 @@ public class ResourceTest @Inject Flyway flyway; - @Inject - VersionService versionService; - @BeforeEach void before() { - flyway.clean(); - flyway.migrate(); + //flyway.clean(); + //flyway.migrate(); } @Test @TestSecurity(user = "user") - void test() + void test_01() { RestAssured.given().body(readFile("/jar/postgresql-42.7.9.jar")).put("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.jar"); RestAssured.given().body(readFile("/jar/postgresql-42.7.9.pom")).put("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.pom"); - byte[] responseJar = RestAssured.given().get("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.jar").getBody().asByteArray(); - String responsePom = RestAssured.given().get("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.pom").getBody().asString(); - String responsePomMd5 = RestAssured.given().get("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.pom.md5").getBody().asString(); + System.out.println("x"); + } - Optional version = versionService.findOptional("org.postgresql", "postgresql", "42.7.9"); + @Test + @TestSecurity(user = "user") + void test_snapshot_01() throws IOException + { + String uploadPom = new String(readFile("/jar/postgresql-42.7.9.pom").readAllBytes(), StandardCharsets.UTF_8); + RestAssured.given().body(uploadPom).put("/maven2/org/postgresql/postgresql/42.7.9-SNAPSHOT/postgresql-42.7.9-20250419.123456-1.pom").then().statusCode(204); + byte[] uploadJar = readFile("/jar/postgresql-42.7.9.jar").readAllBytes(); + RestAssured.given().body(uploadJar).put("/maven2/org/postgresql/postgresql/42.7.9-SNAPSHOT/postgresql-42.7.9-20250419.123456-1.jar").then().statusCode(204); - Assertions.assertTrue(version.isPresent()); - Assertions.assertTrue(responseJar.length > 0); - Assertions.assertTrue(responsePom !=null && responsePom.startsWith(" extensionResult = new ExtensionParser().parse(filename); - Assertions.assertEquals("test", result.base()); - Assertions.assertEquals(FileExt.JAR, result.ext()); - Assertions.assertEquals(FileHash.MD5, result.hashExt()); + Assertions.assertEquals("jackson-core-2.21.0-20250419.123456-1", extensionResult.remainder()); + Assertions.assertEquals(FileExt.JAR, extensionResult.result().ext()); + Assertions.assertEquals(FileHash.MD5, extensionResult.result().hashExt()); } @Test @@ -22,11 +24,11 @@ public class ExtensionParserTest { String filename = "test.pom.sha1"; - ExtensionParser.Result result = ExtensionParser.parse(filename); + ParserResult extensionResult = new ExtensionParser().parse(filename); - Assertions.assertEquals("test", result.base()); - Assertions.assertEquals(FileExt.POM, result.ext()); - Assertions.assertEquals(FileHash.SHA1, result.hashExt()); + Assertions.assertEquals("test", extensionResult.remainder()); + Assertions.assertEquals(FileExt.POM, extensionResult.result().ext()); + Assertions.assertEquals(FileHash.SHA1, extensionResult.result().hashExt()); } @Test @@ -34,10 +36,10 @@ public class ExtensionParserTest { String filename = "test.jar"; - ExtensionParser.Result result = ExtensionParser.parse(filename); + ParserResult extensionResult = new ExtensionParser().parse(filename); - Assertions.assertEquals("test", result.base()); - Assertions.assertEquals(FileExt.JAR, result.ext()); - Assertions.assertNull(result.hashExt()); + Assertions.assertEquals("test", extensionResult.remainder()); + Assertions.assertEquals(FileExt.JAR, extensionResult.result().ext()); + Assertions.assertNull(extensionResult.result().hashExt()); } } diff --git a/src/test/java/dev/dinauer/maven/maven/core/model/SnapshotFileParserTest.java b/src/test/java/dev/dinauer/maven/maven/core/model/SnapshotFileParserTest.java deleted file mode 100644 index c35ecf0..0000000 --- a/src/test/java/dev/dinauer/maven/maven/core/model/SnapshotFileParserTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.dinauer.maven.maven.core.model; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class SnapshotFileParserTest -{ - @Test - void test() - { - String filename = "my-library-1.0.0-20240315.142307-3-tests.jar.md5"; - - SnapshotFile file = SnapshotFileParser.parse("my-library", "1.0.0-SNAPSHOT", filename); - - Assertions.assertEquals("20240315", file.getDate()); - Assertions.assertEquals("142307", file.getTime()); - Assertions.assertEquals(3, file.getBuildNumber()); - Assertions.assertEquals(FileExt.JAR, file.getType()); - Assertions.assertEquals(FileHash.MD5, file.getHash()); - } -} diff --git a/src/test/java/dev/dinauer/maven/maven/core/release/ReleaseServiceTest.java b/src/test/java/dev/dinauer/maven/maven/core/release/ReleaseServiceTest.java new file mode 100644 index 0000000..32677f1 --- /dev/null +++ b/src/test/java/dev/dinauer/maven/maven/core/release/ReleaseServiceTest.java @@ -0,0 +1,20 @@ +package dev.dinauer.maven.maven.core.release; + +import com.fasterxml.jackson.core.JsonProcessingException; +import dev.dinauer.maven.maven.core.MavenService; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class ReleaseServiceTest +{ + @Inject + MavenService mavenService; + + @Test + void test() + { + mavenService.upload("/com/fasterxml/jackson/core/jackson-databind/2.21.2/jackson-databind-2.21.2-tests.jar", null); + } +} diff --git a/src/test/java/dev/dinauer/maven/maven/core/snapshot/SnapshotServiceTest.java b/src/test/java/dev/dinauer/maven/maven/core/snapshot/SnapshotServiceTest.java new file mode 100644 index 0000000..aa09e01 --- /dev/null +++ b/src/test/java/dev/dinauer/maven/maven/core/snapshot/SnapshotServiceTest.java @@ -0,0 +1,20 @@ +package dev.dinauer.maven.maven.core.snapshot; + +import com.fasterxml.jackson.core.JsonProcessingException; +import dev.dinauer.maven.maven.core.MavenService; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class SnapshotServiceTest +{ + @Inject + MavenService mavenService; + + @Test + void test() throws JsonProcessingException + { + mavenService.upload("/com/fasterxml/jackson/core/jackson-databind/2.21.2-SNAPSHOT/jackson-databind-2.21.2-20240315.123456-3.jar", null); + } +} diff --git a/src/test/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParserTest.java b/src/test/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParserTest.java new file mode 100644 index 0000000..9bda95f --- /dev/null +++ b/src/test/java/dev/dinauer/maven/maven/core/snapshot/parser/SnapshotFileParserTest.java @@ -0,0 +1,21 @@ +package dev.dinauer.maven.maven.core.snapshot.parser; + +import dev.dinauer.maven.maven.core.snapshot.SnapshotFile; +import dev.dinauer.maven.maven.core.snapshot.SnapshotPom; +import dev.dinauer.maven.maven.shared.ParserResult; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class SnapshotFileParserTest +{ + @Test + void test() + { + ParserResult result = new SnapshotFileParser("jackson-core", "2.21.0").parse("jackson-core-2.21.0-20250419.123456-1-linux-x86_64"); + + Assertions.assertEquals("20250419", result.result().getDate()); + Assertions.assertEquals("123456", result.result().getTime()); + Assertions.assertEquals(1, result.result().getBuildNumber()); + Assertions.assertEquals("linux-x86_64", result.result().getClassifier()); + } +}