This commit is contained in:
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
||||
*
|
||||
!target/*-runner
|
||||
!target/*-runner.jar
|
||||
!target/lib/*
|
||||
!target/quarkus-app/*
|
||||
25
.github/workflows/build.yml
vendored
Normal file
25
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Maven build
|
||||
run-name: Build application with maven
|
||||
on: [ push ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
MAVEN_ACCESS_TOKEN: ${{ secrets.CI_TOKEN }}
|
||||
MAVEN_REPO_OWNER: ${{ gitea.actor }}
|
||||
steps:
|
||||
- name: Check out latest repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build project
|
||||
run: ./mvnw -s .mvn/settings.xml clean install -DskipTests
|
||||
|
||||
- name: Deploy project
|
||||
run: ./mvnw -s .mvn/settings.xml deploy -DskipTests
|
||||
|
||||
45
.gitignore
vendored
Normal file
45
.gitignore
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
#Maven
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
release.properties
|
||||
.flattened-pom.xml
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
||||
bin/
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
*.ipr
|
||||
*.iml
|
||||
*.iws
|
||||
|
||||
# NetBeans
|
||||
nb-configuration.xml
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
.factorypath
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Vim
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
# Local environment
|
||||
.env
|
||||
|
||||
# Plugin directory
|
||||
/.quarkus/cli/plugins/
|
||||
# TLS Certificates
|
||||
.certs/
|
||||
19
.mvn/settings.xml
Normal file
19
.mvn/settings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
||||
https://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<servers>
|
||||
<server>
|
||||
<id>gitea</id>
|
||||
<configuration>
|
||||
<httpHeaders>
|
||||
<property>
|
||||
<name>Authorization</name>
|
||||
<value>token ${env.MAVEN_ACCESS_TOKEN}</value>
|
||||
</property>
|
||||
</httpHeaders>
|
||||
</configuration>
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
</settings>
|
||||
1
.mvn/wrapper/.gitignore
vendored
Normal file
1
.mvn/wrapper/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
maven-wrapper.jar
|
||||
93
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
93
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Authenticator;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public final class MavenWrapperDownloader {
|
||||
private static final String WRAPPER_VERSION = "3.3.2";
|
||||
|
||||
private static final boolean VERBOSE = Boolean.parseBoolean(System.getenv("MVNW_VERBOSE"));
|
||||
|
||||
public static void main(String[] args) {
|
||||
log("Apache Maven Wrapper Downloader " + WRAPPER_VERSION);
|
||||
|
||||
if (args.length != 2) {
|
||||
System.err.println(" - ERROR wrapperUrl or wrapperJarPath parameter missing");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
log(" - Downloader started");
|
||||
final URL wrapperUrl = URI.create(args[0]).toURL();
|
||||
final String jarPath = args[1].replace("..", ""); // Sanitize path
|
||||
final Path wrapperJarPath = Paths.get(jarPath).toAbsolutePath().normalize();
|
||||
downloadFileFromURL(wrapperUrl, wrapperJarPath);
|
||||
log("Done");
|
||||
} catch (IOException e) {
|
||||
System.err.println("- Error downloading: " + e.getMessage());
|
||||
if (VERBOSE) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(URL wrapperUrl, Path wrapperJarPath)
|
||||
throws IOException {
|
||||
log(" - Downloading to: " + wrapperJarPath);
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
final String username = System.getenv("MVNW_USERNAME");
|
||||
final char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
Path temp = wrapperJarPath
|
||||
.getParent()
|
||||
.resolve(wrapperJarPath.getFileName() + "."
|
||||
+ Long.toUnsignedString(ThreadLocalRandom.current().nextLong()) + ".tmp");
|
||||
try (InputStream inStream = wrapperUrl.openStream()) {
|
||||
Files.copy(inStream, temp, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.move(temp, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} finally {
|
||||
Files.deleteIfExists(temp);
|
||||
}
|
||||
log(" - Downloader complete");
|
||||
}
|
||||
|
||||
private static void log(String msg) {
|
||||
if (VERBOSE) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
20
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
20
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
wrapperVersion=3.3.2
|
||||
distributionType=source
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar
|
||||
34
README.md
Normal file
34
README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# semrack
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Dev mode local execution
|
||||
|
||||
```shell script
|
||||
./mvnw quarkus:dev
|
||||
```
|
||||
|
||||
### Build project
|
||||
|
||||
```shell script
|
||||
./mvnw clean install
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Storage Postgres
|
||||
|
||||
The storage-postgres module use the quarkus jdbc-postgresql extension.
|
||||
|
||||
In dev mode, the database devservices is used. To configure database in production, you need to set the quarkus jdbc parameters :
|
||||
|
||||
quarkus.datasource.jdbc.url=jdbc:postgresql://${semrack.db.host}:${semrack.db.port}/${semrack.db.name}
|
||||
quarkus.datasource.reactive.url=postgresql://${semrack.db.host}:${semrack.db.port}/${semrack.db.name}
|
||||
quarkus.datasource.username=${semrack.db.user}
|
||||
quarkus.datasource.password=${semrack.db.password}
|
||||
|
||||
|
||||
27
docs/semrack-core.md
Normal file
27
docs/semrack-core.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Semrack Core
|
||||
|
||||
Fourni les entités / fonctionalités suivantes :
|
||||
|
||||
- Semdoc : l'entité document, la base de travail
|
||||
- Storage : backend de récupération / stockage des documents
|
||||
- Repository : s'interface en amont du storage. Active les fonctionnalité d'interceptions de lecture, d'écriture et recherche
|
||||
- ReadInterceptor : interception du document en lecture
|
||||
- WriteInterceptor : interception du document en écriture
|
||||
- SearchInterceptor : interception des filtres de recherche
|
||||
|
||||
## Semdoc
|
||||
|
||||
- uid : identifiant unique dans le rack
|
||||
- annotations: écrites uniquement par les intercepteurs
|
||||
- métadonnées: écrite par l'utilisateur, peuvent être altérées par les intercepteurs (validation, securité, etc.)
|
||||
- directives: lors d'un push, renseigne les intercepteurs sur les actions à mener pour l'écriture du document (versioning, annotations, etc.)
|
||||
|
||||
## Directives
|
||||
|
||||
### Snapshot
|
||||
La directive snapshot permet de créer une capture lors du push du document précédent
|
||||
|
||||
directives:
|
||||
snapshot: true | false
|
||||
publish: true | false
|
||||
|
||||
24
integration/semrack-integration/docker-compose.yml
Normal file
24
integration/semrack-integration/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: quarkus
|
||||
ports:
|
||||
- "35532:5432"
|
||||
|
||||
semrack:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: src/main/docker/Dockerfile.native-micro
|
||||
environment:
|
||||
QUARKUS_FLYWAY_ACTIVE: true
|
||||
ports:
|
||||
- "9090:8080"
|
||||
links:
|
||||
- postgres
|
||||
volumes:
|
||||
- ./.env:/work/.env
|
||||
- ./src/main/resources/application.properties:/work/config/application.properties
|
||||
|
||||
|
||||
136
integration/semrack-integration/pom.xml
Normal file
136
integration/semrack-integration/pom.xml
Normal file
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<artifactId>semrack-parent</artifactId>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>semrack-integration</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>generate-code</goal>
|
||||
<goal>generate-code-tests</goal>
|
||||
<goal>native-image-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${org.mapstruct.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<parameters>true</parameters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,98 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/semrack-jvm .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack-jvm
|
||||
#
|
||||
# If you want to include the debug port into your docker image
|
||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||
# when running the container
|
||||
#
|
||||
# Then run the container using :
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack-jvm
|
||||
#
|
||||
# This image uses the `run-java.sh` script to run the application.
|
||||
# This scripts computes the command line to execute your Java application, and
|
||||
# includes memory/GC tuning.
|
||||
# You can configure the behavior using the following environment properties:
|
||||
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||
# of the container available memory as set here. The default is `50` which means 50%
|
||||
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||
# a container without any memory constraints for the container then this option has
|
||||
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||
# when things are happening. This option, if set to true, will set
|
||||
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||
# true").
|
||||
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||
# (example: "20")
|
||||
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||
# (example: "40")
|
||||
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||
# (example: "4")
|
||||
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||
# previous GC times. (example: "90")
|
||||
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||
# contain the necessary JRE command-line options to specify the required GC, which
|
||||
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/openjdk-21:1.21
|
||||
|
||||
ENV LANGUAGE='en_US:en'
|
||||
|
||||
|
||||
# We make four distinct layers so if there are application changes the library layers can be re-used
|
||||
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
|
||||
COPY --chown=185 target/quarkus-app/*.jar /deployments/
|
||||
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
|
||||
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
|
||||
|
||||
EXPOSE 8080
|
||||
USER 185
|
||||
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||
|
||||
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dquarkus.package.jar.type=legacy-jar
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/semrack-legacy-jar .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack-legacy-jar
|
||||
#
|
||||
# If you want to include the debug port into your docker image
|
||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||
# when running the container
|
||||
#
|
||||
# Then run the container using :
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack-legacy-jar
|
||||
#
|
||||
# This image uses the `run-java.sh` script to run the application.
|
||||
# This scripts computes the command line to execute your Java application, and
|
||||
# includes memory/GC tuning.
|
||||
# You can configure the behavior using the following environment properties:
|
||||
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||
# of the container available memory as set here. The default is `50` which means 50%
|
||||
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||
# a container without any memory constraints for the container then this option has
|
||||
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||
# when things are happening. This option, if set to true, will set
|
||||
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||
# true").
|
||||
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||
# (example: "20")
|
||||
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||
# (example: "40")
|
||||
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||
# (example: "4")
|
||||
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||
# previous GC times. (example: "90")
|
||||
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||
# contain the necessary JRE command-line options to specify the required GC, which
|
||||
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/openjdk-21:1.21
|
||||
|
||||
ENV LANGUAGE='en_US:en'
|
||||
|
||||
|
||||
COPY target/lib/* /deployments/lib/
|
||||
COPY target/*-runner.jar /deployments/quarkus-run.jar
|
||||
|
||||
EXPOSE 8080
|
||||
USER 185
|
||||
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||
|
||||
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||
@@ -0,0 +1,29 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dnative
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.native -t quarkus/semrack .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack
|
||||
#
|
||||
# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.5` base image is based on UBI 9.
|
||||
# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`.
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.5
|
||||
WORKDIR /work/
|
||||
RUN chown 1001 /work \
|
||||
&& chmod "g+rwX" /work \
|
||||
&& chown 1001:root /work
|
||||
COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
|
||||
|
||||
EXPOSE 8080
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||
@@ -0,0 +1,32 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||
# It uses a micro base image, tuned for Quarkus native executables.
|
||||
# It reduces the size of the resulting container image.
|
||||
# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image.
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dnative
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/semrack .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/semrack
|
||||
#
|
||||
# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9.
|
||||
# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`.
|
||||
###
|
||||
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
|
||||
WORKDIR /work/
|
||||
RUN chown 1001 /work \
|
||||
&& chmod "g+rwX" /work \
|
||||
&& chown 1001:root /work
|
||||
COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
|
||||
|
||||
EXPOSE 8080
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||
@@ -0,0 +1,24 @@
|
||||
%dev.quarkus.log.min-level=TRACE
|
||||
|
||||
quarkus.hibernate-orm.mapping.format.global=ignore
|
||||
|
||||
# Datasource
|
||||
quarkus.datasource.devservices.port=35432
|
||||
quarkus.hibernate-orm.scripts.generation=none
|
||||
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${semrack.db.host}:${semrack.db.port}/${semrack.db.name}
|
||||
%prod.quarkus.datasource.reactive.url=postgresql://${semrack.db.host}:${semrack.db.port}/${semrack.db.name}
|
||||
%prod.quarkus.datasource.username=${semrack.db.user}
|
||||
%prod.quarkus.datasource.password=${semrack.db.password}
|
||||
|
||||
## Flyway
|
||||
quarkus.flyway.active=false
|
||||
|
||||
# Security
|
||||
quarkus.keycloak.devservices.port=35180
|
||||
quarkus.oidc.client-id=m2m-client
|
||||
quarkus.oidc.credentials.secret=m2m-password
|
||||
quarkus.oidc.discovery-enabled=true
|
||||
%prod.quarkus.oidc.auth-server-url=${semrack.oidc.url}
|
||||
%prod.quarkus.oidc.client-id=${semrack.oidc.client-id}
|
||||
%prod.quarkus.oidc.credentials.secret=${semrack.oidc.client-secret}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
class SemrackApiIT extends SemrackApiTest {
|
||||
// Execute the same tests but in packaged mode.
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package fr.codeanddata;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
@QuarkusTest
|
||||
class SemrackApiTest {
|
||||
@Test
|
||||
void testHelloEndpoint() {
|
||||
given()
|
||||
.when().get("/hello")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("Hello from Quarkus REST"));
|
||||
}
|
||||
|
||||
}
|
||||
72
modules/semrack-api-rest/deployment/pom.xml
Normal file
72
modules/semrack-api-rest/deployment/pom.xml
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-api-rest-deployment</artifactId>
|
||||
<name>Semrack Api Rest - Deployment</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-jackson-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-openapi-deployment</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.quarkus</groupId>-->
|
||||
<!-- <artifactId>quarkus-oidc-deployment</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5-internal</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.api.rest.deployment;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||
|
||||
class SemrackApiRestProcessor {
|
||||
|
||||
private static final String FEATURE = "semrack-api-rest";
|
||||
|
||||
@BuildStep
|
||||
FeatureBuildItem feature() {
|
||||
return new FeatureBuildItem(FEATURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.api.rest.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusDevModeTest;
|
||||
|
||||
public class SemrackApiRestDevModeTest {
|
||||
|
||||
// Start hot reload (DevMode) test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusDevModeTest devModeTest = new QuarkusDevModeTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnDevModeTest() {
|
||||
// Write your dev mode tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-hot-reload for more information
|
||||
Assertions.assertTrue(true, "Add dev mode assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.api.rest.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusUnitTest;
|
||||
|
||||
public class SemrackApiRestTest {
|
||||
|
||||
// Start unit test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnUnitTest() {
|
||||
// Write your unit tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-extensions for more information
|
||||
Assertions.assertTrue(true, "Add some assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
97
modules/semrack-api-rest/integration-tests/pom.xml
Normal file
97
modules/semrack-api-rest/integration-tests/pom.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-api-rest-integration-tests</artifactId>
|
||||
<name>Semrack Api Rest - Integration Tests</name>
|
||||
|
||||
<properties>
|
||||
<skipITs>true</skipITs>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-image</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>${native.surefire.skip}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package fr.codeanddata.semrack.api.rest.it;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
@Path("/semrack-api-rest")
|
||||
@ApplicationScoped
|
||||
public class SemrackApiRestResource {
|
||||
// add some rest methods here
|
||||
|
||||
@GET
|
||||
public String hello() {
|
||||
return "Hello semrack-api-rest";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package fr.codeanddata.semrack.api.rest.it;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
public class SemrackApiRestResourceIT extends SemrackApiRestResourceTest {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package fr.codeanddata.semrack.api.rest.it;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@QuarkusTest
|
||||
public class SemrackApiRestResourceTest {
|
||||
|
||||
@Test
|
||||
public void testHelloEndpoint() {
|
||||
given()
|
||||
.when().get("/semrack-api-rest")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("Hello semrack-api-rest"));
|
||||
}
|
||||
}
|
||||
19
modules/semrack-api-rest/pom.xml
Normal file
19
modules/semrack-api-rest/pom.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>semrack-api-rest-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Semrack Api Rest - Parent</name>
|
||||
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
</modules>
|
||||
</project>
|
||||
78
modules/semrack-api-rest/runtime/pom.xml
Normal file
78
modules/semrack-api-rest/runtime/pom.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-api-rest-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-api-rest</artifactId>
|
||||
<name>Semrack Api Rest - Runtime</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-openapi</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.quarkus</groupId>-->
|
||||
<!-- <artifactId>quarkus-oidc</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-maven-plugin</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>extension-descriptor</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,54 @@
|
||||
package fr.codeanddata.semrack.api.rest;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocStorage;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import fr.codeanddata.semrack.core.models.PushDocumentRequest;
|
||||
import fr.codeanddata.semrack.core.models.SearchRequest;
|
||||
import fr.codeanddata.semrack.core.models.SearchResult;
|
||||
import fr.codeanddata.semrack.core.repositories.SemdocRepository;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.jboss.resteasy.reactive.RestPath;
|
||||
|
||||
@Path("/semrack/documents")
|
||||
//@Authenticated
|
||||
public class SemrackApi {
|
||||
|
||||
@Inject
|
||||
SemdocStorage storage;
|
||||
|
||||
@Inject
|
||||
SemdocRepository repository;
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<SemrackDocument> pushDocument(PushDocumentRequest semrackDocument) {
|
||||
return repository.pushDocument(semrackDocument);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/search")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<SearchResult> searchDocument(SearchRequest query) {
|
||||
return storage.searchDocument(query);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uid}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<SemrackDocument> getDocument(@RestPath String uid) {
|
||||
return storage.readDocument(uid);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{uid}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<SemrackDocument> updateDocument(@RestPath String uid, PushDocumentRequest semrackDocument) {
|
||||
return repository.pushDocument(semrackDocument);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name: Semrack Api Rest
|
||||
#description: Do something useful.
|
||||
metadata:
|
||||
# keywords:
|
||||
# - semrack-api-rest
|
||||
# guide: ... # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
|
||||
# categories:
|
||||
# - "miscellaneous"
|
||||
# status: "preview"
|
||||
59
modules/semrack-core/deployment/pom.xml
Normal file
59
modules/semrack-core/deployment/pom.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-core-deployment</artifactId>
|
||||
<name>Semrack Core - Deployment</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-security-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jackson-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5-internal</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.deployment;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||
|
||||
class SemrackCoreProcessor {
|
||||
|
||||
private static final String FEATURE = "semrack-core";
|
||||
|
||||
@BuildStep
|
||||
FeatureBuildItem feature() {
|
||||
return new FeatureBuildItem(FEATURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package fr.codeanddata.semrack.core.test;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocStorage;
|
||||
import fr.codeanddata.semrack.core.models.SearchRequest;
|
||||
import fr.codeanddata.semrack.core.models.SearchResult;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class MockedStorageImpl implements SemdocStorage {
|
||||
@Override
|
||||
public Uni<SemrackDocument> readDocument(String uid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<SearchResult> searchDocument(SearchRequest query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Long> countDocuments(SearchRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Boolean> documentsExist(SearchRequest query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<SemrackDocument> storeDocument(SemrackDocument document) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.core.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusDevModeTest;
|
||||
|
||||
public class SemrackCoreDevModeTest {
|
||||
|
||||
// Start hot reload (DevMode) test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusDevModeTest devModeTest = new QuarkusDevModeTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnDevModeTest() {
|
||||
// Write your dev mode tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-hot-reload for more information
|
||||
Assertions.assertTrue(true, "Add dev mode assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.core.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusUnitTest;
|
||||
|
||||
public class SemrackCoreTest {
|
||||
|
||||
// Start unit test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnUnitTest() {
|
||||
// Write your unit tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-extensions for more information
|
||||
Assertions.assertTrue(true, "Add some assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
97
modules/semrack-core/integration-tests/pom.xml
Normal file
97
modules/semrack-core/integration-tests/pom.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-core-integration-tests</artifactId>
|
||||
<name>Semrack Core - Integration Tests</name>
|
||||
|
||||
<properties>
|
||||
<skipITs>true</skipITs>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-image</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>${native.surefire.skip}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package fr.codeanddata.semrack.core.it;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
@Path("/semrack-core")
|
||||
@ApplicationScoped
|
||||
public class SemrackCoreResource {
|
||||
// add some rest methods here
|
||||
|
||||
@GET
|
||||
public String hello() {
|
||||
return "Hello semrack-core";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package fr.codeanddata.semrack.core.it;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
public class SemrackCoreResourceIT extends SemrackCoreResourceTest {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package fr.codeanddata.semrack.core.it;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@QuarkusTest
|
||||
public class SemrackCoreResourceTest {
|
||||
|
||||
@Test
|
||||
public void testHelloEndpoint() {
|
||||
given()
|
||||
.when().get("/semrack-core")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("Hello semrack-core"));
|
||||
}
|
||||
}
|
||||
20
modules/semrack-core/pom.xml
Normal file
20
modules/semrack-core/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>semrack-core-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Semrack Core - Parent</name>
|
||||
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
94
modules/semrack-core/runtime/pom.xml
Normal file
94
modules/semrack-core/runtime/pom.xml
Normal file
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
<name>Semrack Core - Runtime</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-maven-plugin</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>extension-descriptor</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocReadContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocReadInterceptor {
|
||||
Uni<Void> interceptSemdocRead(SemdocReadContext context);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocSearchContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocSearchInterceptor {
|
||||
Uni<Void> interceptSemdocSearch(SemdocSearchContext context);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SearchRequest;
|
||||
import fr.codeanddata.semrack.core.models.SearchResult;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocStorage {
|
||||
Uni<SemrackDocument> readDocument(String uid);
|
||||
Uni<SearchResult> searchDocument(SearchRequest query);
|
||||
Uni<Long> countDocuments(SearchRequest request);
|
||||
Uni<Boolean> documentsExist(SearchRequest query);
|
||||
Uni<SemrackDocument> storeDocument(SemrackDocument document);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocWriteInterceptor {
|
||||
Uni<Void> interceptSemdocWrite(SemdocWriteContext context);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.enterprise.inject.spi.CDI;
|
||||
|
||||
public interface SemrackLookupExpression<T> {
|
||||
String apply(Object params);
|
||||
|
||||
default T convert(Object params) {
|
||||
return CDI.current().select(ObjectMapper.class).get().convertValue(params, new TypeReference<T>() {});
|
||||
}
|
||||
|
||||
default T convert(Object params, Class<T> clazz) {
|
||||
return CDI.current().select(ObjectMapper.class).get().convertValue(params, clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package fr.codeanddata.semrack.core.enums;
|
||||
|
||||
public enum SemrackSortDirection {
|
||||
asc, desc
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.exceptions;
|
||||
|
||||
public class SemrackException extends Exception {
|
||||
public SemrackException() {
|
||||
}
|
||||
|
||||
public SemrackException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SemrackException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SemrackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.exceptions;
|
||||
|
||||
public class SemrackRuntimeException extends RuntimeException {
|
||||
public SemrackRuntimeException() {
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package fr.codeanddata.semrack.core.interceptors;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AnnotateWriteInterceptor implements SemdocWriteInterceptor {
|
||||
|
||||
public static final String ANNOTATE_KEY = "annotate";
|
||||
public static final String CUSTOM_PREFIX = "custom/";
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public Uni<Void> interceptSemdocWrite(SemdocWriteContext context) {
|
||||
final Map<String, Object> directives = context.getDirectives();
|
||||
|
||||
if (directives.containsKey(ANNOTATE_KEY)) {
|
||||
final Map<String, Object> annotate = objectMapper.convertValue(directives.get(ANNOTATE_KEY), new TypeReference<Map<String, Object>>() {});
|
||||
annotate.keySet().forEach(key -> context.getNextDocument().getAnnotations().put(CUSTOM_PREFIX + key, annotate.get(key)));
|
||||
}
|
||||
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package fr.codeanddata.semrack.core.interceptors;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import fr.codeanddata.semrack.core.utils.UIDGenerator;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@ApplicationScoped
|
||||
public class PublishWriteInterceptor implements SemdocWriteInterceptor {
|
||||
|
||||
final String PUBLICATION_PREFIX = "publication/";
|
||||
|
||||
@Inject
|
||||
UIDGenerator uidGenerator;
|
||||
|
||||
@Override
|
||||
public Uni<Void> interceptSemdocWrite(SemdocWriteContext context) {
|
||||
final Map<String, Object> directives = context.getDirectives();
|
||||
final SemrackDocument current = context.getCurrentDocument();
|
||||
final SemrackDocument next = context.getNextDocument();
|
||||
|
||||
int version = (int) Optional.ofNullable(current)
|
||||
.map(SemrackDocument::getAnnotations)
|
||||
.map(annotations -> annotations.getOrDefault(PUBLICATION_PREFIX + "version", 0))
|
||||
.orElse(0);
|
||||
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "reference", Optional.ofNullable(current)
|
||||
.map(SemrackDocument::getAnnotations)
|
||||
.map(annotations -> annotations.getOrDefault(PUBLICATION_PREFIX + "reference", next.getUid()))
|
||||
.orElse(next.getUid()));
|
||||
|
||||
final boolean publish = directives.getOrDefault("publish", false).equals(true);
|
||||
final boolean snapshot = directives.getOrDefault("snapshot", publish).equals(true);
|
||||
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "publish", publish);
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "snapshot", snapshot);
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "version", snapshot ? version + 1 : version);
|
||||
if (snapshot && current != null) {
|
||||
next.setUid(uidGenerator.apply(next));
|
||||
}
|
||||
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.mappers;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import fr.codeanddata.semrack.core.models.PushDocumentRequest;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingConstants;
|
||||
|
||||
@Mapper(componentModel = MappingConstants.ComponentModel.CDI)
|
||||
public abstract class SemrackDocumentMapper {
|
||||
@Mapping(source = "uid", target = "uid")
|
||||
@Mapping(source = "metadata", target = "metadata")
|
||||
abstract SemrackDocument toDocument(PushDocumentRequest document);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PaginationInfo {
|
||||
long page;
|
||||
long size;
|
||||
long total;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PushDocumentRequest {
|
||||
/**
|
||||
* L'identifiant unique du document.
|
||||
*/
|
||||
String uid;
|
||||
|
||||
/**
|
||||
* Les directives sont les paramètres d'extensions.
|
||||
* Elles ont pour vocation de générer des actions sur les documents, comme le publish, etc...
|
||||
*/
|
||||
Map<String, Object> directives;
|
||||
|
||||
/**
|
||||
* Le contenu du document.
|
||||
*/
|
||||
Map<String, Object> metadata;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SearchRequest {
|
||||
Map<String, Object> filter;
|
||||
List<SemrackSort> sort;
|
||||
SemrackPagination paginate;
|
||||
List<String> fields;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SearchResult {
|
||||
List<SemrackDocument> documents;
|
||||
PaginationInfo pagination;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocReadContext {
|
||||
|
||||
SemrackDocument currentDocument;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocSearchContext {
|
||||
|
||||
Map<String, Object> search;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocWriteContext {
|
||||
|
||||
/**
|
||||
* Previous stored document
|
||||
*/
|
||||
SemrackDocument currentDocument;
|
||||
|
||||
/**
|
||||
* Document to be store. It initialized with :
|
||||
* - the currentDocument uid if exists, or a new one
|
||||
* - the metadata to be persisted
|
||||
*/
|
||||
SemrackDocument nextDocument;
|
||||
|
||||
/**
|
||||
* The directives to be applied
|
||||
*/
|
||||
Map<String, Object> directives;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection(serialization = true)
|
||||
public class SemrackDocument {
|
||||
|
||||
/**
|
||||
* L'identifiant unique du document.
|
||||
*/
|
||||
String uid;
|
||||
|
||||
/**
|
||||
* Les annotations sont créées par le système, au travers des extensions. Elles sont en lecture seule.
|
||||
* Elles ont pour vocation d'aider au classement et à la recherche du document (tags, catégories, date de création, etc.).
|
||||
*/
|
||||
Map<String, Object> annotations;
|
||||
|
||||
/**
|
||||
* Le contenu du document.
|
||||
*/
|
||||
Map<String, Object> metadata;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SemrackPagination {
|
||||
Integer page;
|
||||
Integer size;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import fr.codeanddata.semrack.core.enums.SemrackSortDirection;
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SemrackSort {
|
||||
String field;
|
||||
SemrackSortDirection direction;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package fr.codeanddata.semrack.core.repositories;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocStorage;
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.exceptions.SemrackRuntimeException;
|
||||
import fr.codeanddata.semrack.core.models.*;
|
||||
import fr.codeanddata.semrack.core.utils.UIDGenerator;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Any;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemdocRepository {
|
||||
|
||||
@Inject
|
||||
SemdocStorage semdocStorage;
|
||||
|
||||
@Inject
|
||||
@Any
|
||||
Instance<SemdocWriteInterceptor> writeInterceptors;
|
||||
|
||||
@Inject
|
||||
UIDGenerator uidGenerator;
|
||||
|
||||
Uni<SearchResult> searchDocument(SearchRequest query) {
|
||||
return semdocStorage.searchDocument(query);
|
||||
}
|
||||
|
||||
public Uni<SemrackDocument> pushDocument(PushDocumentRequest pushDocument) {
|
||||
return Optional.ofNullable(pushDocument.getUid()).map(semdocStorage::readDocument).orElse(Uni.createFrom().nullItem())
|
||||
.chain(currentDocument -> {
|
||||
|
||||
final SemdocWriteContext context = SemdocWriteContext.builder()
|
||||
.directives(pushDocument.getDirectives())
|
||||
.currentDocument(currentDocument)
|
||||
.nextDocument(SemrackDocument.builder()
|
||||
.uid(Optional.ofNullable(currentDocument).map(SemrackDocument::getUid).orElse(uidGenerator.apply(null)))
|
||||
.metadata(pushDocument.getMetadata())
|
||||
.annotations(new HashMap<>())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final AtomicReference<Uni<Void>> documentUni = new AtomicReference<>(Uni.createFrom().voidItem());
|
||||
|
||||
writeInterceptors.stream().forEach(filter -> documentUni.set(documentUni.get().chain(() -> filter.interceptSemdocWrite(context))));
|
||||
return documentUni.get().chain(() -> semdocStorage.storeDocument(context.getNextDocument()));
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<SemrackDocument> getOrCreate(SearchRequest query, PushDocumentRequest toCreate) {
|
||||
return searchDocument(query)
|
||||
.chain(searchResult -> {
|
||||
if (searchResult.getDocuments().isEmpty()) {
|
||||
return pushDocument(toCreate);
|
||||
} else if (searchResult.getDocuments().size() > 1) {
|
||||
throw new SemrackRuntimeException("Multiple documents found");
|
||||
} else {
|
||||
return Uni.createFrom().item(searchResult.getDocuments().getFirst());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package fr.codeanddata.semrack.core.services;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemrackLookupExpression;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.enterprise.inject.Any;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemrackLookupService {
|
||||
|
||||
@Inject
|
||||
@Any
|
||||
Instance<SemrackLookupExpression<?>> operators;
|
||||
|
||||
final Map<String, SemrackLookupExpression<?>> operatorsIndex = new HashMap<>();
|
||||
|
||||
void startup(@Observes StartupEvent event) {
|
||||
operators.stream()
|
||||
.filter(s -> s.getClass().getSuperclass().isAnnotationPresent(Identifier.class))
|
||||
.forEach(s -> {
|
||||
Identifier identifier = s.getClass().getSuperclass().getAnnotation(Identifier.class);
|
||||
operatorsIndex.put(identifier.value(), s);
|
||||
});
|
||||
}
|
||||
|
||||
public String lookup(Map<String, Object> lookupExpression) {
|
||||
final Set<String> lookupKeys = lookupExpression.keySet();
|
||||
if (lookupKeys.isEmpty()) {
|
||||
return "";
|
||||
} else if (lookupKeys.size() > 1) {
|
||||
throw new RuntimeException("Only one lookup expression is allowed");
|
||||
} else {
|
||||
final String lookupKey = lookupKeys.stream().findFirst().get();
|
||||
if (! operatorsIndex.containsKey(lookupKey)) {
|
||||
throw new RuntimeException("Unknown lookup expression '" + lookupKey + "'");
|
||||
} else {
|
||||
final SemrackLookupExpression<?> lookup = operatorsIndex.get(lookupKey);
|
||||
final Object lookupParams = lookupExpression.get(lookupKey);
|
||||
return lookup.apply(lookupParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fr.codeanddata.semrack.core.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemdocUtils {
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
public <T> T map(Object map, Class<T> clazz) {
|
||||
return objectMapper.convertValue(map, clazz);
|
||||
}
|
||||
|
||||
public <T> T map(Object map, TypeReference<T> typeRef) {
|
||||
return objectMapper.convertValue(map, typeRef);
|
||||
}
|
||||
|
||||
public Map<String, Object> remap(Object map) {
|
||||
return objectMapper.convertValue(map, new TypeReference<>() {});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.core.utils;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ApplicationScoped
|
||||
public class UIDGenerator implements Function<SemrackDocument, String> {
|
||||
|
||||
@Override
|
||||
public String apply(SemrackDocument semrackDocument) {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
final LocalDateTime now = LocalDateTime.now();
|
||||
final long timestamp = now.toInstant(ZoneOffset.UTC).toEpochMilli();
|
||||
|
||||
return DigestUtils.sha256Hex(uuid + timestamp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name: Semrack Core
|
||||
#description: Do something useful.
|
||||
metadata:
|
||||
# keywords:
|
||||
# - semrack-core
|
||||
# guide: ... # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
|
||||
# categories:
|
||||
# - "miscellaneous"
|
||||
# status: "preview"
|
||||
72
modules/semrack-storage-postgres/deployment/pom.xml
Normal file
72
modules/semrack-storage-postgres/deployment/pom.xml
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-storage-postgres-deployment</artifactId>
|
||||
<name>Semrack Storage Postgres - Deployment</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-hibernate-reactive-panache-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-reactive-pg-client-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-flyway-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jdbc-postgresql-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5-internal</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.deployment;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||
|
||||
class SemrackStoragePostgresProcessor {
|
||||
|
||||
private static final String FEATURE = "semrack-storage-postgres";
|
||||
|
||||
@BuildStep
|
||||
FeatureBuildItem feature() {
|
||||
return new FeatureBuildItem(FEATURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusDevModeTest;
|
||||
|
||||
public class SemrackStoragePostgresDevModeTest {
|
||||
|
||||
// Start hot reload (DevMode) test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusDevModeTest devModeTest = new QuarkusDevModeTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnDevModeTest() {
|
||||
// Write your dev mode tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-hot-reload for more information
|
||||
Assertions.assertTrue(true, "Add dev mode assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.test;
|
||||
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import io.quarkus.test.QuarkusUnitTest;
|
||||
|
||||
public class SemrackStoragePostgresTest {
|
||||
|
||||
// Start unit test with your extension loaded
|
||||
@RegisterExtension
|
||||
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
|
||||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||
|
||||
@Test
|
||||
public void writeYourOwnUnitTest() {
|
||||
// Write your unit tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-extensions for more information
|
||||
Assertions.assertTrue(true, "Add some assertions to " + getClass().getName());
|
||||
}
|
||||
}
|
||||
97
modules/semrack-storage-postgres/integration-tests/pom.xml
Normal file
97
modules/semrack-storage-postgres/integration-tests/pom.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-storage-postgres-integration-tests</artifactId>
|
||||
<name>Semrack Storage Postgres - Integration Tests</name>
|
||||
|
||||
<properties>
|
||||
<skipITs>true</skipITs>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-image</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>${native.surefire.skip}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package fr.codeanddata.semrack.storage.postgres.it;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
@Path("/semrack-storage-postgres")
|
||||
@ApplicationScoped
|
||||
public class SemrackStoragePostgresResource {
|
||||
// add some rest methods here
|
||||
|
||||
@GET
|
||||
public String hello() {
|
||||
return "Hello semrack-storage-postgres";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.it;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
public class SemrackStoragePostgresResourceIT extends SemrackStoragePostgresResourceTest {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.it;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@QuarkusTest
|
||||
public class SemrackStoragePostgresResourceTest {
|
||||
|
||||
@Test
|
||||
public void testHelloEndpoint() {
|
||||
given()
|
||||
.when().get("/semrack-storage-postgres")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("Hello semrack-storage-postgres"));
|
||||
}
|
||||
}
|
||||
20
modules/semrack-storage-postgres/pom.xml
Normal file
20
modules/semrack-storage-postgres/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>semrack-storage-postgres-parent</artifactId>
|
||||
<name>Semrack Storage Postgres - Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
96
modules/semrack-storage-postgres/runtime/pom.xml
Normal file
96
modules/semrack-storage-postgres/runtime/pom.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-storage-postgres-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-storage-postgres</artifactId>
|
||||
<name>Semrack Storage Postgres - Runtime</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-hibernate-reactive-panache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-reactive-pg-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-flyway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jdbc-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-database-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-maven-plugin</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>extension-descriptor</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.dtos;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class InLookupParams {
|
||||
String field;
|
||||
List<String> values;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.entities;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Entity(name = "SemrackDocument")
|
||||
@Table(name = "semrack_document")
|
||||
public class SemrackDocumentEntity extends PanacheEntity implements Serializable {
|
||||
@Column(unique = true, columnDefinition = "varchar(256)")
|
||||
String uid;
|
||||
|
||||
@JdbcTypeCode(SqlTypes.JSON)
|
||||
SemrackDocument document;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import fr.codeanddata.semrack.core.services.SemrackLookupService;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Identifier("and")
|
||||
@ApplicationScoped
|
||||
public class AndLookup implements SemrackJpaLookupExpression<List<Map<String, Object>>> {
|
||||
|
||||
@Inject
|
||||
SemrackLookupService lookupService;
|
||||
|
||||
@Override
|
||||
public String apply(Object expressions) {
|
||||
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
||||
return String.join(" AND ", typedExpressions.stream().map(lookupService::lookup).toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
@Identifier("contains")
|
||||
@ApplicationScoped
|
||||
public class ContainsLookup implements SemrackJpaLookupExpression<Object> {
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public String apply(Object params) {
|
||||
try {
|
||||
return "document @> '" + objectMapper.writeValueAsString(params) + "'";
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import fr.codeanddata.semrack.core.exceptions.SemrackRuntimeException;
|
||||
import fr.codeanddata.semrack.storage.postgres.dtos.InLookupParams;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Identifier("in")
|
||||
@ApplicationScoped
|
||||
public class InLookup implements SemrackJpaLookupExpression<InLookupParams> {
|
||||
|
||||
@Override
|
||||
public String apply(Object params) {
|
||||
final InLookupParams inLookupParams = convert(params, InLookupParams.class);
|
||||
final List<String> fields = new ArrayList<>(Arrays.asList(inLookupParams.getField().split("\\.")));
|
||||
if (fields.isEmpty()) {
|
||||
throw new SemrackRuntimeException("Field expected");
|
||||
}
|
||||
|
||||
String query = "->> '" + fields.removeLast() + "'";
|
||||
if (!fields.isEmpty()) {
|
||||
query = "-> '" + String.join("' -> '", fields) + "' " + query;
|
||||
}
|
||||
|
||||
return "document " + query + " in " + "('" + String.join("', '", inLookupParams.getValues()) + "')";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import fr.codeanddata.semrack.core.services.SemrackLookupService;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Identifier("or")
|
||||
@ApplicationScoped
|
||||
public class OrLookup implements SemrackJpaLookupExpression<List<Map<String, Object>>> {
|
||||
|
||||
@Inject
|
||||
SemrackLookupService lookupService;
|
||||
|
||||
@Override
|
||||
public String apply(Object expressions) {
|
||||
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
||||
return String.join(" OR ", typedExpressions.stream().map(lookupService::lookup).toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemrackLookupExpression;
|
||||
|
||||
public interface SemrackJpaLookupExpression<T> extends SemrackLookupExpression<T> {
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.storage;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.codeanddata.semrack.core.SemdocStorage;
|
||||
import fr.codeanddata.semrack.core.enums.SemrackSortDirection;
|
||||
import fr.codeanddata.semrack.core.models.*;
|
||||
import fr.codeanddata.semrack.core.services.SemrackLookupService;
|
||||
import fr.codeanddata.semrack.core.utils.UIDGenerator;
|
||||
import fr.codeanddata.semrack.storage.postgres.entities.SemrackDocumentEntity;
|
||||
import fr.codeanddata.semrack.storage.postgres.utils.PathMapper;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemdocJpaStorage implements SemdocStorage, PanacheRepository<SemrackDocumentEntity> {
|
||||
|
||||
@Inject
|
||||
UIDGenerator generator;
|
||||
|
||||
@Inject
|
||||
PathMapper pathMapper;
|
||||
|
||||
@Inject
|
||||
SemrackLookupService lookupService;
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
@WithSession
|
||||
public Uni<SemrackDocument> readDocument(String uid) {
|
||||
return find("uid = ?1", uid)
|
||||
.firstResult().map(d -> Optional.ofNullable(d).map(SemrackDocumentEntity::getDocument).orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
@WithSession
|
||||
public Uni<SearchResult> searchDocument(SearchRequest query) {
|
||||
return search(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Long> countDocuments(SearchRequest request) {
|
||||
final String lookup = lookupService.lookup(request.getFilter());
|
||||
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
||||
|
||||
return getSession()
|
||||
.chain(s -> s.createNativeQuery("SELECT count(id) FROM semrack_document" + whereClause, Long.class).getSingleResultOrNull())
|
||||
.map(count -> count == null ? 0 : count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Boolean> documentsExist(SearchRequest query) {
|
||||
return countDocuments(query)
|
||||
.map(c -> c > 0);
|
||||
}
|
||||
|
||||
@WithTransaction
|
||||
@Override
|
||||
public Uni<SemrackDocument> storeDocument(SemrackDocument document) {
|
||||
if (document.getUid() == null) {
|
||||
return createDocument(document);
|
||||
} else {
|
||||
return find("uid = ?1", document.getUid())
|
||||
.count()
|
||||
.chain(n -> n == 0 ? createDocument(document) : updateDocument(document));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO err : handle existing document
|
||||
@WithTransaction
|
||||
Uni<SemrackDocument> createDocument(SemrackDocument document) {
|
||||
final String uid = document.getUid() == null ? generator.apply(document) : document.getUid();
|
||||
document.setUid(uid);
|
||||
final SemrackDocumentEntity entity = SemrackDocumentEntity.builder()
|
||||
.uid(uid)
|
||||
.document(document)
|
||||
.build();
|
||||
return persist(entity).map(SemrackDocumentEntity::getDocument);
|
||||
}
|
||||
|
||||
// TODO err : document not exists
|
||||
@WithTransaction
|
||||
Uni<SemrackDocument> updateDocument(SemrackDocument document) {
|
||||
return update("uid = ?1, document = ?2 WHERE uid = ?1", document.getUid(), document)
|
||||
.map(x -> document);
|
||||
}
|
||||
|
||||
Uni<SearchResult> search(SearchRequest request) {
|
||||
final String baseQuery = buildBaseQuery(request);
|
||||
|
||||
final StringBuilder sorting = new StringBuilder();
|
||||
if (request.getSort() != null && !request.getSort().isEmpty()) {
|
||||
sorting.append(" ORDER BY ");
|
||||
sorting.append(String.join(", ", request.getSort().stream().map(sort -> sort.getField() + " " + Optional.ofNullable(sort.getDirection()).orElse(SemrackSortDirection.asc).name()).toList()));
|
||||
}
|
||||
|
||||
final StringBuilder paginate = new StringBuilder();
|
||||
if (request.getPaginate() != null) {
|
||||
final SemrackPagination pagination = request.getPaginate();
|
||||
final Integer size = pagination.getSize() == null ? 200 : pagination.getSize();
|
||||
final Integer page = pagination.getPage() == null ? 0 : pagination.getPage();
|
||||
|
||||
paginate.append(" LIMIT ").append(size).append(" OFFSET ").append(size * page);
|
||||
}
|
||||
|
||||
return getSession()
|
||||
.chain(s -> {
|
||||
final SearchResult searchResult = SearchResult.builder().build();
|
||||
return countDocuments(request)
|
||||
.invoke(count -> searchResult.setPagination(PaginationInfo.builder()
|
||||
.page(Optional.ofNullable(request.getPaginate()).map(SemrackPagination::getPage).orElse(0))
|
||||
.size(Optional.ofNullable(request.getPaginate()).map(SemrackPagination::getSize).orElse(0))
|
||||
.total(count)
|
||||
.build()))
|
||||
.call(() -> s
|
||||
.createNativeQuery(baseQuery + sorting + paginate, Object.class).getResultList()
|
||||
.invoke(results -> searchResult.setDocuments(project(request.getFields(), results))))
|
||||
.map(count -> searchResult);
|
||||
});
|
||||
}
|
||||
|
||||
String buildBaseQuery(SearchRequest request) {
|
||||
final String lookup = lookupService.lookup(request.getFilter());
|
||||
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
||||
|
||||
if (request.getFields() == null || request.getFields().isEmpty()) {
|
||||
return "SELECT document FROM semrack_document" + whereClause;
|
||||
} else {
|
||||
return "SELECT " + toJsonbPathExtract(request.getFields()) + " FROM semrack_document" + whereClause;
|
||||
}
|
||||
}
|
||||
|
||||
String toJsonbPathExtract(List<String> fields) {
|
||||
return String.join(",", fields.stream().map(field -> {
|
||||
final String serializedField = "'" + String.join("','", field.split("\\.")) + "'";
|
||||
return "jsonb_extract_path(document, " + serializedField + ")";
|
||||
}).toList());
|
||||
}
|
||||
|
||||
List<SemrackDocument> project(List<String> fields, Object results) {
|
||||
final List<?> projectedResults = objectMapper.convertValue(results, List.class);
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
return projectedResults.stream().map(result -> objectMapper.convertValue(result, SemrackDocument.class)).toList();
|
||||
} else {
|
||||
return projectedResults.stream().map(result -> {
|
||||
final List<Object> row = fields.size() == 1 ? List.of(result) : objectMapper.convertValue(result, new TypeReference<>() {
|
||||
});
|
||||
final List<Object> rowMut = new ArrayList<>(row);
|
||||
final List<String> fieldCp = new ArrayList<>(fields);
|
||||
final Map<String, Object> document = new HashMap<>();
|
||||
while (!fieldCp.isEmpty() && !row.isEmpty()) {
|
||||
final String field = fieldCp.removeFirst();
|
||||
final Object value = rowMut.removeFirst();
|
||||
pathMapper.map(field, document, value);
|
||||
}
|
||||
return objectMapper.convertValue(document, SemrackDocument.class);
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ApplicationScoped
|
||||
public class PathMapper {
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
public Map<String, Object> map(String path, Object value) {
|
||||
return map(path, new HashMap<>(), value);
|
||||
}
|
||||
|
||||
public Map<String, Object> map(String path, Map<String, Object> target, Object value) {
|
||||
setValue(new ArrayList<>(Stream.of(path.split("\\.")).toList()), target, value);
|
||||
return target;
|
||||
}
|
||||
|
||||
void setValue(List<String> paths, Map<String, Object> container, Object value) {
|
||||
if (!paths.isEmpty()) {
|
||||
final String key = paths.removeFirst();
|
||||
if (paths.isEmpty()) {
|
||||
container.put(key, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!container.containsKey(key) || !(container.get(key) instanceof Map)) {
|
||||
container.put(key, new HashMap<>());
|
||||
}
|
||||
|
||||
final Map<String, Object> target = objectMapper.convertValue(container.get(key), new TypeReference<>() {});
|
||||
container.put(key, target);
|
||||
setValue(paths, target, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name: Semrack Storage Postgres
|
||||
#description: Do something useful.
|
||||
metadata:
|
||||
# keywords:
|
||||
# - semrack-storage-postgres
|
||||
# guide: ... # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
|
||||
# categories:
|
||||
# - "miscellaneous"
|
||||
# status: "preview"
|
||||
@@ -0,0 +1,7 @@
|
||||
quarkus.datasource.db-kind=postgresql
|
||||
quarkus.flyway.enabled=true
|
||||
quarkus.flyway.active=false
|
||||
quarkus.flyway.migrate-at-start=true
|
||||
|
||||
quarkus.native.resources.includes=src/main/resources/db/migration/**
|
||||
quarkus.native.additional-build-args=-H:SerializationConfigurationResources=serialization-config.json
|
||||
@@ -0,0 +1,10 @@
|
||||
create sequence semrack_document_SEQ start with 1 increment by 50;
|
||||
create table semrack_document
|
||||
(
|
||||
id bigint not null,
|
||||
uid varchar(256) unique,
|
||||
document jsonb,
|
||||
primary key (id)
|
||||
);
|
||||
alter table semrack_document
|
||||
add constraint UK307dbjrfh151l0r7bb36xdwew unique (uid);
|
||||
@@ -0,0 +1,3 @@
|
||||
[
|
||||
{"name": "java.lang.String"}
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.inject.Inject;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@QuarkusTest
|
||||
class ContainsLookupTest {
|
||||
|
||||
@Inject
|
||||
@Identifier("contains")
|
||||
ContainsLookup subject;
|
||||
|
||||
@Test
|
||||
void testLookup() {
|
||||
final String lookup = subject.apply(Map.of("product", Map.of("sku", "xxx")));
|
||||
final String expectedLookup = "document @> '{\"product\":{\"sku\":\"xxx\"}}'";
|
||||
Assertions.assertEquals(expectedLookup, lookup);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.operators;
|
||||
|
||||
import fr.codeanddata.semrack.storage.postgres.dtos.InLookupParams;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.inject.Inject;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@QuarkusTest
|
||||
class InLookupTest {
|
||||
|
||||
@Inject
|
||||
@Identifier("in")
|
||||
InLookup subject;
|
||||
|
||||
@Test
|
||||
void testConversion() {
|
||||
final String field = "root.parent.child.field";
|
||||
final List<String> values = List.of("un", "deux", "trois");
|
||||
final Map<String, Object> inParams = Map.of(
|
||||
"field", field,
|
||||
"values", values
|
||||
);
|
||||
|
||||
final InLookupParams convertedParams = subject.convert(inParams, InLookupParams.class);
|
||||
Assertions.assertEquals(field, convertedParams.getField());
|
||||
Assertions.assertEquals(values, convertedParams.getValues());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLookup() {
|
||||
final String lookup = subject.apply(Map.of(
|
||||
"field", "lookup.field",
|
||||
"values", List.of("list", "of", "values")));
|
||||
final String expectedLookup = "document -> 'lookup' ->> 'field' in ('list', 'of', 'values')";
|
||||
Assertions.assertEquals(expectedLookup, lookup);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package fr.codeanddata.semrack.storage.postgres.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.inject.Inject;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@QuarkusTest
|
||||
public class PathMapperTest {
|
||||
|
||||
@Inject
|
||||
PathMapper pathMapper;
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
void testMapper() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
final Map<String, Object> root = new HashMap<>();
|
||||
map.put("root", root);
|
||||
root.put("name", "bob");
|
||||
|
||||
pathMapper.map("root.child.subchild1.value", map, 1);
|
||||
pathMapper.map("root.child.subchild2.value", map, 2);
|
||||
pathMapper.map("hello", map, "world");
|
||||
|
||||
Assertions.assertEquals("world", map.get("hello"));
|
||||
Assertions.assertEquals(1, conv(conv(conv(map, "root"), "child"), "subchild1").get("value"));
|
||||
Assertions.assertEquals(2, conv(conv(conv(map, "root"), "child"), "subchild2").get("value"));
|
||||
Assertions.assertEquals("bob", conv(map, "root").get( "name"));
|
||||
}
|
||||
|
||||
Map<String, Object> conv(Map<String, Object> container, String key) {
|
||||
return objectMapper.convertValue(container.get(key), new TypeReference<>() {});
|
||||
}
|
||||
}
|
||||
332
mvnw
vendored
Executable file
332
mvnw
vendored
Executable file
@@ -0,0 +1,332 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, publish 3.3.2
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ]; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ]; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ]; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ]; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false
|
||||
darwin=false
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true ;;
|
||||
Darwin*)
|
||||
darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"
|
||||
export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -r /etc/gentoo-release ]; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] \
|
||||
&& CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw; then
|
||||
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME="$(
|
||||
cd "$JAVA_HOME" || (
|
||||
echo "cannot cd into $JAVA_HOME." >&2
|
||||
exit 1
|
||||
)
|
||||
pwd
|
||||
)"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
|
||||
if $darwin; then
|
||||
javaHome="$(dirname "$javaExecutable")"
|
||||
javaExecutable="$(cd "$javaHome" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f "$javaExecutable")"
|
||||
fi
|
||||
javaHome="$(dirname "$javaExecutable")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ]; then
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(
|
||||
\unset -f command 2>/dev/null
|
||||
\command -v java
|
||||
)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ]; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set." >&2
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
if [ -z "$1" ]; then
|
||||
echo "Path not specified to find_maven_basedir" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ]; do
|
||||
if [ -d "$wdir"/.mvn ]; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(
|
||||
cd "$wdir/.." || exit 1
|
||||
pwd
|
||||
)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(
|
||||
cd "$basedir" || exit 1
|
||||
pwd
|
||||
)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the storage with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' <"$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in wrapperUrl)
|
||||
wrapperUrl="$safeValue"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget >/dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl >/dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in wrapperSha256Sum)
|
||||
wrapperSha256Sum=$value
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] \
|
||||
&& CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] \
|
||||
&& MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user