diff --git a/.github/workflows/http-tests.yml b/.github/workflows/http-tests.yml
index 22e9740bd8..adac057374 100644
--- a/.github/workflows/http-tests.yml
+++ b/.github/workflows/http-tests.yml
@@ -8,11 +8,16 @@ jobs:
runs-on: ubuntu-latest
env:
ASF_ARCHIVE: https://archive.apache.org/dist/
- JENA_VERSION: 4.7.0
+ JENA_VERSION: 6.1.0
BASE_URI: https://localhost:4443/
steps:
- name: Install Linux packages
run: sudo apt-get update && sudo apt-get install -qq raptor2-utils && sudo apt-get install curl
+ - name: Set up Java 21
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: '21'
- name: Download Jena
run: curl -sS --fail "${{ env.ASF_ARCHIVE }}jena/binaries/apache-jena-${{ env.JENA_VERSION }}.tar.gz" -o "${{ runner.temp }}/jena.tar.gz"
- name: Unpack Jena
@@ -49,6 +54,12 @@ jobs:
run: ./run.sh "$PWD/ssl/owner/cert.pem" "${{ secrets.HTTP_TEST_OWNER_CERT_PASSWORD }}" "$PWD/ssl/secretary/cert.pem" "${{ secrets.HTTP_TEST_SECRETARY_CERT_PASSWORD }}"
shell: bash
working-directory: http-tests
+ - name: Dump container logs on failure
+ if: failure()
+ run: docker compose --env-file ./http-tests/.env logs --no-color
+ - name: Dump Tomcat logs from linkeddatahub container on failure
+ if: failure()
+ run: docker compose --env-file ./http-tests/.env exec -T linkeddatahub sh -c 'for f in /usr/local/tomcat/logs/*; do echo "=== $f ==="; cat "$f"; done' || true
- name: Stop Docker containers and remove volumes
run: docker compose --env-file ./http-tests/.env down -v
- name: Remove Docker containers
diff --git a/Dockerfile b/Dockerfile
index 3d8066e6e8..a5fdd51e49 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,8 @@
-FROM maven:3.8.4-openjdk-17 AS maven
+FROM maven:3.9-eclipse-temurin-21 AS maven
# download and extract Jena
-ARG JENA_VERSION=4.7.0
+ARG JENA_VERSION=6.1.0
ARG JENA_TAR_URL="https://archive.apache.org/dist/jena/binaries/apache-jena-${JENA_VERSION}.tar.gz"
@@ -22,7 +22,7 @@ RUN mvn -Pstandalone clean install
# ==============================
-FROM atomgraph/letsencrypt-tomcat:10.1.46
+FROM atomgraph/letsencrypt-tomcat:10.1.52
LABEL maintainer="martynas@atomgraph.com"
diff --git a/docker-compose.yml b/docker-compose.yml
index c95560dbd4..02b5f52033 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -20,7 +20,7 @@ volumes:
varnish_end_user_cache:
services:
nginx:
- image: nginx:1.23.3
+ image: nginx:1.31.1
mem_limit: 128m
configs:
- source: nginx_conf
@@ -105,7 +105,7 @@ services:
- ./config/dataspaces.trig:/var/linkeddatahub/datasets/dataspaces.trig
- ./config/system.trig:/var/linkeddatahub/datasets/system.trig
fuseki-admin:
- image: atomgraph/fuseki:4.7.0
+ image: atomgraph/fuseki:6.1.0
user: root # otherwise fuseki user does not have permissions to the mounted folder which is owner by root
expose:
- 3030
@@ -114,7 +114,7 @@ services:
- ./fuseki/admin:/fuseki/databases
command: [ "--config", "/fuseki/config.ttl" ]
fuseki-end-user:
- image: atomgraph/fuseki:4.7.0
+ image: atomgraph/fuseki:6.1.0
user: root # otherwise the fuseki user does not have permissions to the mounted folder which is owner by root
expose:
- 3030
@@ -123,7 +123,7 @@ services:
- ./fuseki/end-user:/fuseki/databases
command: [ "--config", "/fuseki/config.ttl" ]
varnish-frontend:
- image: varnish:7.3.0
+ image: varnish:7.7.3
user: root # otherwise varnish user does not have permissions to the mounted folder which is owner by root
configs:
- source: varnish-frontend_vcl
@@ -136,7 +136,7 @@ services:
entrypoint: varnishd
command: [ "-F", "-f", "/etc/varnish/default.vcl", "-a", "http=:6060,HTTP", "-a", "proxy=:8443,PROXY", "-p", "feature=+http2", "-s", "file,/var/lib/varnish/storage.bin,3G", "-t", "86400" ] # -F: foreground, -f: config, -a: listeners, -p: http2, -s: storage, -t: TTL
varnish-admin:
- image: varnish:7.3.0
+ image: varnish:7.7.3
user: root # otherwise the varnish user does not have permissions to the mounted folder which is owner by root
configs:
- source: varnish-admin_vcl
@@ -147,7 +147,7 @@ services:
entrypoint: varnishd
command: [ "-F", "-f", "/etc/varnish/default.vcl", "-a", "http=:80,HTTP", "-a", "proxy=:8443,PROXY", "-p", "feature=+http2", "-s", "malloc,1G", "-t", "86400", "-p", "timeout_idle=60s" ] # -F: foreground, -f: config, -a: listeners, -p: http2 + idle timeout, -s: storage, -t: TTL
varnish-end-user:
- image: varnish:7.3.0
+ image: varnish:7.7.3
user: root # otherwise varnish user does not have permissions to the mounted folder which is owner by root
configs:
- source: varnish-end-user_vcl
diff --git a/platform/entrypoint.sh b/platform/entrypoint.sh
index a737c3a6b2..a67ef53832 100755
--- a/platform/entrypoint.sh
+++ b/platform/entrypoint.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
set -e
+set -x # DEBUG: trace every command (revert before merge)
+exec 2>&1 # DEBUG: merge stderr into stdout so the trace lands in docker logs
# set timezone
diff --git a/pom.xml b/pom.xml
index abcad6aaab..3294574f1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,28 +86,28 @@
jakarta.servlet
jakarta.servlet-api
- 5.0.0
+ 6.0.0
provided
org.glassfish.jersey.connectors
jersey-apache-connector
- 3.1.0
+ 3.1.11
org.glassfish.jersey.media
jersey-media-multipart
- 3.1.0
+ 3.1.11
org.glassfish.jersey.media
jersey-media-json-processing
- 3.1.0
+ 3.1.11
com.sun.mail
jakarta.mail
- 2.0.1
+ 2.0.2
com.google.guava
@@ -117,7 +117,7 @@
com.atomgraph.etl.csv
csv2rdf
- 2.1.11
+ 2.2.0
@@ -129,57 +129,67 @@
org.apache.jena
jena-shacl
- 4.7.0
+ 6.1.0
+
+
+ org.apache.jena
+ jena-arq
+ 6.1.0
+
+
+ com.github.jsonld-java
+ jsonld-java
+ 0.13.4
${project.groupId}
twirl
- 1.0.33
+ 1.1.0
${project.groupId}
client
- 4.2.11
+ 4.3.0
classes
${project.groupId}
client
- 4.2.11
+ 4.3.0
war
org.apache.httpcomponents
httpclient-cache
- 4.5.13
+ 4.5.14
com.auth0
java-jwt
- 3.19.3
+ 3.19.4
net.jodah
expiringmap
- 0.5.10
+ 0.5.11
org.jsoup
jsoup
- 1.15.3
+ 1.22.1
org.apache.tomcat
tomcat-coyote
- 10.1.2
+ 10.1.52
jar
- junit
- junit
- 4.13.2
+ org.junit.jupiter
+ junit-jupiter
+ 5.11.4
test
@@ -188,6 +198,12 @@
5.12.0
test
+
+ org.mockito
+ mockito-junit-jupiter
+ 5.12.0
+ test
+
@@ -216,10 +232,15 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.2
+
org.apache.maven.plugins
maven-release-plugin
- 2.5.3
+ 3.3.1
release
@@ -227,10 +248,10 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.10.1
+ 3.14.1
- 17
- 17
+ 21
+ 21
-XDignore.symbol.file
@@ -243,7 +264,7 @@
org.sonatype.central
central-publishing-maven-plugin
- 0.9.0
+ 0.10.0
true
central-portal-snapshots
@@ -254,7 +275,7 @@
org.codehaus.mojo
exec-maven-plugin
- 3.0.0
+ 3.6.3
find-xsl-files
@@ -287,7 +308,7 @@
org.honton.chas
readfiles-maven-plugin
- 0.0.1
+ 0.1.0
read-comma-separated-xsl-file-list
@@ -338,7 +359,7 @@
com.github.eirslett
frontend-maven-plugin
- 1.15.1
+ 1.15.4
v22.16.0
11.4.2
@@ -366,7 +387,7 @@
org.apache.maven.plugins
maven-war-plugin
- 3.3.2
+ 3.5.1
${build.warName}
${project.build.directory}/${build.warName}
@@ -432,7 +453,7 @@
org.apache.maven.plugins
maven-source-plugin
- 3.2.1
+ 3.4.0
attach-sources
@@ -445,7 +466,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.2.0
+ 3.12.0
attach-javadocs
diff --git a/src/main/java/com/atomgraph/linkeddatahub/client/SesameProtocolClient.java b/src/main/java/com/atomgraph/linkeddatahub/client/SesameProtocolClient.java
index 0cb29e2c2a..1adae78188 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/client/SesameProtocolClient.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/client/SesameProtocolClient.java
@@ -123,7 +123,7 @@ public static MultivaluedMap solutionMapToMultivaluedMap(QuerySo
{
String varName = it.next();
RDFNode node = qsm.get(varName);
- params.add("$" + varName, NodeFmtLib.str(node.asNode()));
+ params.add("$" + varName, NodeFmtLib.strNT(node.asNode()));
}
return params;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
index 095219cf30..4ccefa319f 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
@@ -46,15 +46,13 @@
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.SecurityContext;
import jakarta.ws.rs.core.UriInfo;
-import org.apache.jena.iri.IRI;
-import org.apache.jena.iri.IRIFactory;
+import org.apache.jena.irix.IRIx;
import org.apache.jena.ontology.Ontology;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.riot.system.Checker;
import org.apache.jena.update.UpdateRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -182,15 +180,12 @@ public Response post(UpdateRequest update, @QueryParam(USING_GRAPH_URI) List
""";
- @Test(expected = RiotException.class)
+ @Test
public void testBillionLaughs() {
- Model m = ModelFactory.createDefaultModel();
-
- ByteArrayInputStream bais = new ByteArrayInputStream(MALICIOUS.getBytes(StandardCharsets.UTF_8));
-
- RDFParser parser = RDFParser.create()
- .lang(Lang.RDFXML)
- .errorHandler(ErrorHandlerFactory.errorHandlerStrict)
- .checking(true)
- .base("http://example.org/")
- .source(bais)
- .build();
-
- System.out.println("Starting parse...");
- parser.parse(StreamRDFLib.graph(m.getGraph()));
- System.out.println("Model size: " + m.size());
+ assertThrows(RiotException.class, () -> {
+ Model m = ModelFactory.createDefaultModel();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(MALICIOUS.getBytes(StandardCharsets.UTF_8));
+
+ RDFParser parser = RDFParser.create()
+ .lang(Lang.RDFXML)
+ .errorHandler(ErrorHandlerFactory.errorHandlerStrict)
+ .checking(true)
+ .base("http://example.org/")
+ .source(bais)
+ .build();
+
+ System.out.println("Starting parse...");
+ parser.parse(StreamRDFLib.graph(m.getGraph()));
+ System.out.println("Model size: " + m.size());
+ });
}
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/client/filter/ClientUriRewriteFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/client/filter/ClientUriRewriteFilterTest.java
index 1c874c19b8..ce3d6e89fa 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/client/filter/ClientUriRewriteFilterTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/client/filter/ClientUriRewriteFilterTest.java
@@ -34,8 +34,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import org.junit.Test;
-import static org.junit.Assert.*;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
/**
* Unit tests for {@link ClientUriRewriteFilter}.
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilterTest.java
index 745ecd94dd..2321ecf817 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilterTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilterTest.java
@@ -24,11 +24,11 @@
import java.io.IOException;
import java.net.URI;
import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.*;
@@ -37,7 +37,7 @@
*
* @author Martynas Jusevičius {@literal }
*/
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
public class ProxyRequestFilterTest
{
@@ -47,7 +47,7 @@ public class ProxyRequestFilterTest
private ProxyRequestFilter filter;
- @Before
+ @BeforeEach
public void setUp()
{
filter = new ProxyRequestFilter();
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java
index fd22dae189..b72bc4b653 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java
@@ -16,9 +16,10 @@
package com.atomgraph.linkeddatahub.server.util;
import com.atomgraph.linkeddatahub.server.exception.InternalURLException;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import java.net.URI;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* Unit tests for URLValidator SSRF protection.
@@ -32,34 +33,34 @@
public class URLValidatorTest
{
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testNullURI()
{
- new URLValidator(false).validate(null);
+ assertThrows(IllegalArgumentException.class, () -> new URLValidator(false).validate(null));
}
- @Test(expected = InternalURLException.class)
+ @Test
public void testLinkLocalIPv4Blocked()
{
- new URLValidator(false).validate(URI.create("http://169.254.1.1:8080/test"));
+ assertThrows(InternalURLException.class, () -> new URLValidator(false).validate(URI.create("http://169.254.1.1:8080/test")));
}
- @Test(expected = InternalURLException.class)
+ @Test
public void testPrivateClass10Blocked()
{
- new URLValidator(false).validate(URI.create("http://10.0.0.1:8080/test"));
+ assertThrows(InternalURLException.class, () -> new URLValidator(false).validate(URI.create("http://10.0.0.1:8080/test")));
}
- @Test(expected = InternalURLException.class)
+ @Test
public void testPrivateClass172Blocked()
{
- new URLValidator(false).validate(URI.create("http://172.16.0.0:8080/test"));
+ assertThrows(InternalURLException.class, () -> new URLValidator(false).validate(URI.create("http://172.16.0.0:8080/test")));
}
- @Test(expected = InternalURLException.class)
+ @Test
public void testPrivateClass192Blocked()
{
- new URLValidator(false).validate(URI.create("http://192.168.1.1:8080/test"));
+ assertThrows(InternalURLException.class, () -> new URLValidator(false).validate(URI.create("http://192.168.1.1:8080/test")));
}
@Test