This is an automated email from the ASF dual-hosted git repository.

afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 989604848c80f451ba64802e3e9598ecea4bb0d9
Author: Andy Seaborne <[email protected]>
AuthorDate: Wed May 27 14:45:13 2026 +0100

    Reserved prefix for URLs
---
 .../main/java/org/apache/jena/fuseki/Fuseki.java   | 44 +++++++++++++++-------
 .../org/apache/jena/fuseki/main/FusekiServer.java  |  2 +
 .../apache/jena/fuseki/main/runner/FusekiArgs.java | 11 +++---
 .../apache/jena/fuseki/mod/admin/FMod_Admin.java   | 12 +++---
 .../jena/fuseki/mod/admin/LocalhostOnly.java       |  6 ++-
 .../fuseki/mod/prometheus/FMod_Prometheus.java     |  4 +-
 .../org/apache/jena/fuseki/mod/ui/FMod_UI.java     | 12 +++---
 7 files changed, 61 insertions(+), 30 deletions(-)

diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
index d4b742d6b2..6b45d40f5a 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/Fuseki.java
@@ -43,27 +43,27 @@ public class Fuseki {
     // General fixed constants.
 
     /** Path as package name */
-    static public final String PATH               = "org.apache.jena.fuseki";
+    public static final String PATH               = "org.apache.jena.fuseki";
 
     /** a unique IRI for the Fuseki namespace */
-    static public final String FusekiIRI          = 
"http://jena.apache.org/Fuseki";;
+    public static final String FusekiIRI          = 
"http://jena.apache.org/Fuseki";;
 
     /**
      * A Fuseki base IRI for {@link Symbol Symbols}
      */
-    static public final String FusekiSymbolIRI    = 
"http://jena.apache.org/fuseki#";;
+    public static final String FusekiSymbolIRI    = 
"http://jena.apache.org/fuseki#";;
 
     /** Dummy base URI string for parsing SPARQL Query and Update requests */
-    static public final String BaseParserSPARQL   = 
"http://server/unset-base/";;
+    public static final String BaseParserSPARQL   = 
"http://server/unset-base/";;
 
     /** Dummy base URI string for parsing SPARQL Query and Update requests */
-    static public final String BaseUpload         = 
"http://server/unset-base/";;
+    public static final String BaseUpload         = 
"http://server/unset-base/";;
 
     /** The name of the Fuseki server.*/
-    static public final String  NAME              = "Apache Jena Fuseki";
+    public static final String  NAME              = "Apache Jena Fuseki";
 
     /** Version of this Fuseki instance */
-    static public final String  VERSION           = 
Version.versionForClass(Fuseki.class).orElse("<development>");
+    public static final String  VERSION           = 
Version.versionForClass(Fuseki.class).orElse("<development>");
 
     /**
      * Supporting Graph Store Protocol direct naming.
@@ -91,12 +91,28 @@ public class Fuseki {
      * <b>Note</b><br/>
      * GSP Direct Naming was primarily implemented to provide two 
implementations for the SPARQL 1.1 implementation report.
      */
-    static public final boolean GSP_DIRECT_NAMING = true;
+    public static final boolean GSP_DIRECT_NAMING = true;
+
+    /**
+     * Path prefix reserved for admin and server operations such as /$/ping
+     */
+    public static final String reservedPathPrefix = "/$/";
+    /**
+     * Return a URL in the server function area.
+     */
+    public static String serverFunctionPath(String path) {
+        if ( path.startsWith(reservedPathPrefix) )
+            return path;
+        if ( path.startsWith("/") )
+            return "/$"+path;
+        else
+            return reservedPathPrefix+path;
+    }
 
     /** Are we in development mode?  That means a SNAPSHOT, or no VERSION
      * because maven has not filtered the fuseki-properties.xml file.
      */
-    public static boolean   developmentMode;
+    public static boolean developmentMode;
     static {
         // See ServletBase.setCommonheaders
         // If it look like a SNAPSHOT, or it's not set, we are in development 
mode.
@@ -104,8 +120,9 @@ public class Fuseki {
     }
 
     // @formatter:off
-    public static boolean   outputJettyServerHeader     = developmentMode;
-    public static boolean   outputFusekiServerHeader    = developmentMode;
+    public static boolean outputJettyServerHeader   = developmentMode;
+    public static boolean outputFusekiServerHeader  = developmentMode;
+    // @formatter:on
 
     /**
      * Initialize is class.
@@ -114,7 +131,7 @@ public class Fuseki {
     public static void initConsts() {}
 
     /** An identifier for the HTTP Fuseki server instance */
-    static public final String  serverHttpName          = NAME + " (" + 
VERSION + ")";
+    public static final String  serverHttpName          = NAME + " (" + 
VERSION + ")";
 
     /** Logger name for operations */
     public static final String  actionLogName     = PATH + ".Fuseki";
@@ -171,7 +188,8 @@ public class Fuseki {
     public static final Logger  compactLog        = 
LoggerFactory.getLogger(compactLogName);
 
     // There isn't an ideal status code for a cancelled query.
-    // HTTP 408 "Request timeout" which is about connection management, not 
for general timeouts.
+    // HTTP 408 "Request timeout" is not appropriate.
+    // It is about connection management, not for general timeouts.
     public static int SC_QueryCancelled                 = 
HttpSC.SERVICE_UNAVAILABLE_503;
 
     // Servlet context attribute names used by the core engine.
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
index e0a14a1b2b..e391ca9109 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -138,6 +138,8 @@ public class FusekiServer {
 
     /** Return a fresh builder configured according to the the argument list */
     public static Builder builder(String...args) {
+        if ( args == null || args.length == 0 )
+            return new Builder();
         return new Builder().applyArgs(args);
     }
 
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/runner/FusekiArgs.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/runner/FusekiArgs.java
index 65ceb3deda..a37e402643 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/runner/FusekiArgs.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/runner/FusekiArgs.java
@@ -22,6 +22,7 @@
 package org.apache.jena.fuseki.main.runner;
 
 import static arq.cmdline.ModAssembler.assemblerDescDecl;
+import static org.apache.jena.fuseki.Fuseki.serverFunctionPath;
 import static org.apache.jena.fuseki.main.runner.SetupType.*;
 
 import java.nio.file.Path;
@@ -593,11 +594,11 @@ public class FusekiArgs extends CmdGeneral {
 
         if ( serverArgs.validators ) {
             // Validators.
-            builder.addServlet("/$/validate/query",     new QueryValidator());
-            builder.addServlet("/$/validate/update",    new UpdateValidator());
-            builder.addServlet("/$/validate/iri",       new IRIValidator());
-            builder.addServlet("/$/validate/langtag",   new 
LangTagValidator());
-            builder.addServlet("/$/validate/data",      new DataValidator());
+            builder.addServlet(serverFunctionPath("/validate/query"),     new 
QueryValidator());
+            builder.addServlet(serverFunctionPath("/validate/update"),    new 
UpdateValidator());
+            builder.addServlet(serverFunctionPath("/validate/iri"),       new 
IRIValidator());
+            builder.addServlet(serverFunctionPath("/validate/langtag"),   new 
LangTagValidator());
+            builder.addServlet(serverFunctionPath("/validate/data"),      new 
DataValidator());
         }
 
         // Apply argument for the database services
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/FMod_Admin.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/FMod_Admin.java
index fb5f86f3eb..81c3e48238 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/FMod_Admin.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/FMod_Admin.java
@@ -21,6 +21,8 @@
 
 package org.apache.jena.fuseki.mod.admin;
 
+import static org.apache.jena.fuseki.Fuseki.serverFunctionPath;
+
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.HashSet;
@@ -194,11 +196,11 @@ public class FMod_Admin implements FusekiModule {
         // Security is performed by FMod_Shiro.
         ActionCtl actionBackup = new ActionBackup();
         builder
-                .addServlet("/$/datasets/*", new ActionDatasets())
-                .addServlet("/$/server", new ActionServerStatus())
-                .addServlet("/$/backup/*", actionBackup)
-                .addServlet("/$/backups/*", actionBackup)
-                .addServlet("/$/backups-list", new ActionBackupList())
+                .addServlet(serverFunctionPath("/datasets/*"), new 
ActionDatasets())
+                .addServlet(serverFunctionPath("/server"), new 
ActionServerStatus())
+                .addServlet(serverFunctionPath("/backup/*"), actionBackup)
+                .addServlet(serverFunctionPath("/backups/*"), actionBackup)
+                .addServlet(serverFunctionPath("/backups-list"), new 
ActionBackupList())
 
                 // Enables the task subsystem
                 .enableTasks(true)
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/LocalhostOnly.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/LocalhostOnly.java
index d9955b445d..4559ca9844 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/LocalhostOnly.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/LocalhostOnly.java
@@ -21,6 +21,8 @@
 
 package org.apache.jena.fuseki.mod.admin;
 
+import static org.apache.jena.fuseki.Fuseki.serverFunctionPath;
+
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collection;
@@ -56,7 +58,9 @@ public class LocalhostOnly implements Filter {
     public LocalhostOnly() { }
 
     // "permit" and "deny" lists
-    private List<String> secured = Arrays.asList("/$/backup", "/$/compact", 
"/$/datasets");
+    private List<String> secured = Arrays.asList(serverFunctionPath("/backup"),
+                                                 
serverFunctionPath("/compact"),
+                                                 
serverFunctionPath("/datasets"));
 
     @Override
     public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/FMod_Prometheus.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/FMod_Prometheus.java
index 8ad80184a9..dc3973e3a2 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/FMod_Prometheus.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/FMod_Prometheus.java
@@ -21,6 +21,8 @@
 
 package org.apache.jena.fuseki.mod.prometheus;
 
+import static org.apache.jena.fuseki.Fuseki.serverFunctionPath;
+
 import java.util.Set;
 
 import org.apache.jena.fuseki.Fuseki;
@@ -56,7 +58,7 @@ public class FMod_Prometheus implements FusekiModule {
     @Override public void prepare(FusekiServer.Builder serverBuilder, 
Set<String> datasetNames, Model configModel) {
         metricsProvider = new PrometheusMetricsProvider();
         serverBuilder.setServletAttribute(Fuseki.attrMetricsProvider, 
metricsProvider);
-        serverBuilder.addServlet("/$/metrics", new ActionMetrics());
+        serverBuilder.addServlet(serverFunctionPath("/metrics"), new 
ActionMetrics());
     }
 
     @Override public void server(FusekiServer server) {
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/ui/FMod_UI.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/ui/FMod_UI.java
index 09e6cc3635..be1989cf1c 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/ui/FMod_UI.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/ui/FMod_UI.java
@@ -21,6 +21,8 @@
 
 package org.apache.jena.fuseki.mod.ui;
 
+import static org.apache.jena.fuseki.Fuseki.serverFunctionPath;
+
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Set;
@@ -115,11 +117,11 @@ public class FMod_UI implements FusekiModule {
         }
 
         builder.staticFileBase(uiAppLocation)       // Set the UI files area.
-               .addServlet("/$/validate/query",     new QueryValidator())
-               .addServlet("/$/validate/update",    new UpdateValidator())
-               .addServlet("/$/validate/iri",       new IRIValidator())
-               .addServlet("/$/validate/langtag",   new LangTagValidator())
-               .addServlet("/$/validate/data",      new DataValidator())
+               .addServlet(serverFunctionPath("/validate/query"),     new 
QueryValidator())
+               .addServlet(serverFunctionPath("/validate/update"),    new 
UpdateValidator())
+               .addServlet(serverFunctionPath("/validate/iri"),       new 
IRIValidator())
+               .addServlet(serverFunctionPath("/validate/langtag"),   new 
LangTagValidator())
+               .addServlet(serverFunctionPath("/validate/data"),      new 
DataValidator())
                .enableStats(true);
         // LOG.info("Fuseki UI loaded");
     }

Reply via email to