This is an automated email from the ASF dual-hosted git repository. andy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/jena.git
commit 3f3e36559fb17e0848e1aab036481ac5af63f4b3 Author: Andy Seaborne <[email protected]> AuthorDate: Wed Dec 4 18:38:22 2024 +0000 Record configuration before wiring modifications --- .../jena/sparql/util/ContextAccumulator.java | 8 ++--- .../main/java/org/apache/jena/atlas/io/IOX.java | 26 ++++++++++++++-- .../org/apache/jena/fuseki/ctl/ActionStats.java | 1 - .../org/apache/jena/fuseki/main/FusekiServer.java | 28 +++++++++++++---- .../apache/jena/fuseki/main/cmds/FusekiMain.java | 35 ++++++++++++---------- .../org/apache/jena/fuseki/mgt/ActionDatasets.java | 10 ++++--- .../org/apache/jena/fuseki/TS_FusekiWebapp.java | 5 ++-- .../{TestAdmin.java => TestWebappAdmin.java} | 2 +- .../{TestAdminAPI.java => TestWebappAdminAPI.java} | 2 +- .../apache/jena/fuseki/TestWebappFileUpload.java | 1 + 10 files changed, 80 insertions(+), 38 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/ContextAccumulator.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/ContextAccumulator.java index 74998f5adb..52e91147a6 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/ContextAccumulator.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/ContextAccumulator.java @@ -43,7 +43,7 @@ public class ContextAccumulator { private Context baseContext = null; // Context when built - private Context builtContext = null; + private Context builtContext = null; public static ContextAccumulator newBuilder() { return new ContextAccumulator(); @@ -77,7 +77,7 @@ public class ContextAccumulator { /** * If no explicit base, this is the default. It will be copied to isolate it at the build point. - * Default implement is to return ARQ.getContext(). + * Default implementation is to return ARQ.getContext(). */ protected Context baseContext() { return ARQ.getContext(); } @@ -108,7 +108,7 @@ public class ContextAccumulator { */ public Context context() { // Freeze and return. - return getOrBuiltContext(); + return getOrBuildContext(); } /** @@ -129,7 +129,7 @@ public class ContextAccumulator { } // Build once. - private Context getOrBuiltContext() { + private Context getOrBuildContext() { if ( builtContext == null ) builtContext = buildProcess(); return builtContext; diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java index 02b09e1bba..b5ea543111 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IOX.java @@ -337,9 +337,31 @@ public class IOX { throw exceptionMaker.apply("File not found: "+path); if ( Files.isDirectory(path) ) throw exceptionMaker.apply("Is a directory: "+path); - if ( !Files.isRegularFile(path) ) + if ( ! Files.isRegularFile(path) ) throw exceptionMaker.apply("Not a regular file: "+path); - if ( !Files.isReadable(path) ) + if ( ! Files.isReadable(path) ) + throw exceptionMaker.apply("Not readable: "+path); + } + + /** + * Check whether a file path points to a readable directory. + * Generate an exception if not. + */ + public static void checkReadableDirectory(String directory, Function<String, RuntimeException> exceptionMaker) { + Path path = Path.of(directory); + checkReadableDirectory(path, exceptionMaker); + } + + /** + * Check whether a file path points to a readable directory. + * Generate an exception if not. + */ + public static void checkReadableDirectory(Path path, Function<String, RuntimeException> exceptionMaker) { + if ( ! Files.exists(path) ) + throw exceptionMaker.apply("File not found: "+path); + if ( ! Files.isDirectory(path) ) + throw exceptionMaker.apply("Not a directory: "+path); + if ( ! Files.isReadable(path) ) throw exceptionMaker.apply("Not readable: "+path); } } diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java index 5a674354c0..3972c9e6fa 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionStats.java @@ -40,7 +40,6 @@ public class ActionStats extends ActionContainerItem @Override public void validate(HttpAction action) {} - // This does not consult the system database for dormant etc. protected JsonValue execCommonContainer(HttpAction action) { if ( action.verbose ) action.log.info(format("[%d] GET stats all", action.id)); 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 9ed7ef42b0..812d26b1f2 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 @@ -61,6 +61,7 @@ import org.apache.jena.rdf.model.*; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.assembler.AssemblerUtils; import org.apache.jena.sparql.util.Context; +import org.apache.jena.sparql.util.ContextAccumulator; import org.apache.jena.sys.JenaSystem; import org.apache.jena.system.G; import org.apache.jena.system.RDFDataException; @@ -142,11 +143,26 @@ public class FusekiServer { * still be created for the server to be able to provide the action. An endpoint * dispatches to an operation, and an operation maps to an implementation. This is a * specialised operation - normal use is the operation {@link #create()}. + * @deprecated Use {@link #create(OperationRegistry, Context)}. */ + @Deprecated(forRemoval = true) public static Builder create(OperationRegistry serviceDispatchRegistry) { - return new Builder(serviceDispatchRegistry); + return create(serviceDispatchRegistry, Fuseki.getContext()); } + /** + * Return a builder, with a custom set of operation-action mappings. An endpoint must + * still be created for the server to be able to provide the action. An endpoint + * dispatches to an operation, and an operation maps to an implementation. This is a + * specialised operation - normal use is the operation {@link #create()}. + */ + public static Builder create(OperationRegistry serviceDispatchRegistry, Context context) { + if ( context == null ) + context = Fuseki.getContext(); + return new Builder(serviceDispatchRegistry, context); + } + + /** * Default port when running in Java via {@code FusekiServer....build()}. * The server will be http://localhost:3330. @@ -446,7 +462,7 @@ public class FusekiServer { private SecurityHandler securityHandler = null; private Map<String, Object> servletAttr = new HashMap<>(); - //private Context context = null; + private final ContextAccumulator context; // The default CORS settings. private static final Map<String, String> corsInitParamsDft = new LinkedHashMap<>(); @@ -467,13 +483,13 @@ public class FusekiServer { // Builder with standard operation-action mapping. private Builder() { this.operationRegistry = OperationRegistry.createStd(); + this.context = ContextAccumulator.newBuilder(()->Fuseki.getContext().copy()); } // Builder with provided operation-action mapping. - private Builder(OperationRegistry operationRegistry) { - // Isolate. - this.operationRegistry = OperationRegistry.createEmpty(); - OperationRegistry.copyConfig(operationRegistry, this.operationRegistry); + private Builder(OperationRegistry operationRegistry, Context context) { + this.operationRegistry = new OperationRegistry(operationRegistry); + this.context = ContextAccumulator.newBuilder(()->context.copy()); } /** diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java index b7a754cd64..f3966f5cc8 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java @@ -240,9 +240,11 @@ public class FusekiMain extends CmdARQ { } private void argumentsSetup() { - getUsage().startCategory("Fuseki Main"); + getUsage().startCategory("Fuseki"); - // Control the order! + add(argConfig, "--config=FILE", + "Use a configuration file to determine the services"); + // ---- Describe the dataset on the command line. add(argMem, "--mem", "Create an in-memory, non-persistent dataset for the server"); add(argFile, "--file=FILE", @@ -257,25 +259,33 @@ public class FusekiMain extends CmdARQ { "Create an in-memory, non-persistent dataset using TDB (testing only)"); add(argRDFS, "--rdfs=FILE", "Apply RDFS on top of the dataset"); - add(argConfig, "--config=FILE", - "Use a configuration file to determine the services"); + add(argUpdate, "--update", + "Allow updates (via SPARQL Update and SPARQL HTTP Update)"); addModule(modDataset); + // ---- Server setup add(argEmpty); // Hidden add(argPort, "--port", "Listen on this port number"); add(argLocalhost, "--localhost", "Listen only on the localhost interface"); - add(argTimeout, "--timeout=", - "Global timeout applied to queries (value in ms) -- format is X[,Y] "); - add(argUpdate, "--update", - "Allow updates (via SPARQL Update and SPARQL HTTP Update)"); add(argGZip, "--gzip=on|off", - "Enable GZip compression (HTTP Accept-Encoding) if request header set"); + "Enable GZip compression (HTTP Accept-Encoding) if request header set"); add(argBase, "--base=DIR", "Directory for static content"); add(argContextPath, "--contextPath=PATH", "Context path for the server"); + add(argHttps, "--https=CONF", + "https certificate access details. JSON file { \"cert\":FILE , \"passwd\"; SECRET } "); + add(argHttpsPort, "--httpsPort=NUM", + "https port (default port is 3043)"); + add(argPasswdFile, "--passwd=FILE", + "Password file"); + + add(argTimeout, "--timeout=", + "Global timeout applied to queries (value in ms) -- format is X[,Y] "); + + // ---- Servlets add(argSparqler, "--sparqler=DIR", "Run with SPARQLer services Directory for static content"); add(argValidators, "--validators", @@ -285,13 +295,6 @@ public class FusekiMain extends CmdARQ { add(argAuth, "--auth=[basic|digest]", "Run the server using basic or digest authentication"); - add(argHttps, "--https=CONF", - "https certificate access details. JSON file { \"cert\":FILE , \"passwd\"; SECRET } "); - add(argHttpsPort, "--httpsPort=NUM", - "https port (default port is 3043)"); - - add(argPasswdFile, "--passwd=FILE", - "Password file"); add(argJettyConfig, "--jetty=FILE", "jetty.xml server configuration"); add(argCORS, "--cors=FILE", "Configure CORS settings from file"); diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java index 109332f8ad..a6a48657b0 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java @@ -141,10 +141,6 @@ public class ActionDatasets extends ActionContainerItem { else assemblerFromBody(action, dest); - Model model = ModelFactory.createDefaultModel(); - model.add(modelData); - AssemblerUtils.addRegistered(model); - // ---- // Keep a persistent copy immediately. This is not used for // anything other than being "for the record". @@ -152,6 +148,12 @@ public class ActionDatasets extends ActionContainerItem { try ( OutputStream outCopy = IO.openOutputFile(systemFileCopy) ) { RDFDataMgr.write(outCopy, modelData, Lang.TURTLE); } + + Model model = ModelFactory.createDefaultModel(); + model.add(modelData); + // Add the dataset and graph wiring. + AssemblerUtils.addRegistered(model); + // ---- // Process configuration. diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TS_FusekiWebapp.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TS_FusekiWebapp.java index 03220d4027..cb517c964c 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TS_FusekiWebapp.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TS_FusekiWebapp.java @@ -26,15 +26,14 @@ import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.Suite; - @RunWith(Suite.class) @Suite.SuiteClasses( { TestWebappSPARQLProtocol.class , TestWebappAuthQuery_JDK.class , TestWebappAuthUpdate_JDK.class , TestWebappFileUpload.class - , TestAdmin.class - , TestAdminAPI.class + , TestWebappAdmin.class + , TestWebappAdminAPI.class , TestWebappServerReadOnly.class , TestWebappMetrics.class }) diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdmin.java similarity index 99% rename from jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java rename to jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdmin.java index 7a89107326..fc60dda045 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdmin.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdmin.java @@ -56,7 +56,7 @@ import org.awaitility.Awaitility; import org.junit.*; /** Tests of the admin functionality */ -public class TestAdmin extends AbstractFusekiWebappTest { +public class TestWebappAdmin extends AbstractFusekiWebappTest { // Name of the dataset in the assembler file. static String dsTest = "test-ds1"; diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdminAPI.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdminAPI.java similarity index 98% rename from jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdminAPI.java rename to jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdminAPI.java index 729ff40ac5..7c1ba82d44 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestAdminAPI.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappAdminAPI.java @@ -38,7 +38,7 @@ import org.junit.Test; /** More tests of the admin functionality * See also TestAdmin. */ -public class TestAdminAPI extends AbstractFusekiWebappTest { +public class TestWebappAdminAPI extends AbstractFusekiWebappTest { @Test public void add_delete_api_1() throws Exception { if ( org.apache.jena.tdb1.sys.SystemTDB.isWindows ) diff --git a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappFileUpload.java b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappFileUpload.java index b834966b37..15fc83787a 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappFileUpload.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestWebappFileUpload.java @@ -40,6 +40,7 @@ import org.junit.Test; * Tests for multi-part file upload. */ public class TestWebappFileUpload extends AbstractFusekiWebappTest { + @Test public void upload_gsp_01() { FileSender x = new FileSender(ServerCtl.serviceGSP() + "?default");
