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 bc2ad4323829912e9a8ee66490dfa0e0e1c7226c Author: Andy Seaborne <[email protected]> AuthorDate: Fri Jul 25 19:40:00 2025 +0100 GH-3348: FusekiServerRunner and FusekiMainRunner --- .../main/java/org/apache/jena/fuseki/Fuseki.java | 18 ++-- .../jena-fuseki-main/src/main/java/fuseki/run.java | 10 +- .../apache/jena/fuseki/main/FusekiMainRunner.java | 80 ++++++++++++++ .../org/apache/jena/fuseki/main/FusekiServer.java | 16 ++- .../apache/jena/fuseki/main/cmds/FusekiMain.java | 5 +- .../jena/fuseki/main/cmds/FusekiServerCmd.java | 8 +- .../main/sys/FusekiServerArgsCustomiser.java | 10 +- .../jena/fuseki/mod/FusekiServerModules.java | 42 ++++++++ .../apache/jena/fuseki/mod/FusekiServerRunner.java | 94 +++-------------- .../apache/jena/fuseki/mod/shiro/FMod_Shiro.java | 4 - .../fuseki/{mod => server}/FusekiServerRunner.java | 68 ++++++------ .../org/apache/jena/fuseki/TC_FusekiServer.java | 4 +- .../apache/jena/fuseki/main/TestConfigFile.java | 2 +- .../jena/fuseki/main/TestCrossOriginFilter.java | 6 +- .../org/apache/jena/fuseki/mod/TS_FusekiMods.java | 8 +- .../fuseki/mod/admin/FusekiServerPerTestClass.java | 9 +- .../TS_FusekiServer.java} | 14 +-- .../fuseki/{mod => server}/TestFusekiServer.java | 5 +- .../jena/fuseki/server/TestFusekiServerCmd.java | 117 +++++++++++++++++++++ .../org/apache/jena/fuseki/cmd/FusekiArgs.java | 3 +- 20 files changed, 351 insertions(+), 172 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 beca3d7f2a..e7a996dd11 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 @@ -169,23 +169,21 @@ public class Fuseki { public static final String compactLogName = PATH + ".Compact"; public static final Logger compactLog = LoggerFactory.getLogger(compactLogName);; - /** Instance of log for config server messages. - * This is the global default used to set attribute - * in each server created. - */ - public static boolean verboseLogging = false; - - // Servlet context attribute names, - + // Servlet context attribute names used by the core engine. + // Also in FusekiServerCtl for Fuseki server public static final String attrVerbose = "org.apache.jena.fuseki:verbose"; public static final String attrNameRegistry = "org.apache.jena.fuseki:DataAccessPointRegistry"; public static final String attrOperationRegistry = "org.apache.jena.fuseki:OperationRegistry"; + public static final String attrMetricsProvider = "org.apache.jena.fuseki:MetricsProvider"; + + // Use by jena-fuseki-access public static final String attrAuthorizationService = "org.apache.jena.fuseki:AuthorizationService"; - // The Fuseki Server + + // Servlet context attribute names used by Fuseki Server. + // The server (so we can go from servlet context, available in request, to the server. public static final String attrFusekiServer = "org.apache.jena.fuseki:Server"; // The FusekiServerCtl object for the admin area; may be null public static final String attrFusekiServerCtl = "org.apache.jena.fuseki:ServerCtl"; - public static final String attrMetricsProvider = "org.apache.jena.fuseki:MetricsProvider"; public static void setVerbose(ServletContext cxt, boolean verbose) { cxt.setAttribute(attrVerbose, Boolean.valueOf(verbose)); diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/fuseki/run.java b/jena-fuseki2/jena-fuseki-main/src/main/java/fuseki/run.java index 78622d174f..195ce8464a 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/fuseki/run.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/fuseki/run.java @@ -18,16 +18,16 @@ package fuseki; +import org.apache.jena.fuseki.main.FusekiMainRunner; + /** * Run FusekiMain. + * @deprecated Use {@link FusekiMainRunner#run}. */ +@Deprecated(forRemoval = true) public class run { - // This class must not depend on any Jena code (it would trigger - // early logging initialization) except FusekiLogging.setLogging. - //static { FusekiLogging.setLogging(); } - public static void main (String... args) { // This does FusekiLogging.setLogging - org.apache.jena.fuseki.main.cmds.FusekiMainCmd.main(args); + FusekiMainRunner.run(args); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiMainRunner.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiMainRunner.java new file mode 100644 index 0000000000..9a1da1843a --- /dev/null +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiMainRunner.java @@ -0,0 +1,80 @@ +/* + * 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 org.apache.jena.fuseki.main; + +import java.net.BindException; + +import org.apache.jena.fuseki.Fuseki; +import org.apache.jena.fuseki.FusekiException; +import org.apache.jena.fuseki.main.cmds.FusekiMain; +import org.apache.jena.fuseki.main.sys.FusekiModules; + +/** + * Functions for building and runner a {@link FusekiServer} configured from command line arguments. + * + * @see {@link FusekiServerRunner0} for similar functionality except it is also initialized with {@link FusekiModules} as well. + */ +public class FusekiMainRunner { + + /** + * Run a plain {@link FusekiServer}. + * @param Command line arguments. + * @return Return the running server. + */ + public static FusekiServer runAsync(String... args) { + FusekiServer server = construct(args); + try { + return server.start(); + } catch (FusekiException ex) { + if ( ex.getCause() instanceof BindException ) { + Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port in use"); + System.exit(1); + } + throw ex; + } catch (Exception ex) { + throw new FusekiException("Failed to start server: " + ex.getMessage(), ex); + } + } + + /** + * Run a plain {@link FusekiServer}. + * This function does not return. + */ + public static void run(String... args) { + FusekiServer server = runAsync(args); + server.join(); + } + + /** + * Build but do not start, a {@link FusekiServer}. + */ + public static FusekiServer construct(String... args) { + FusekiServer.Builder builder = builder(args); + return builder.build(); + } + + /** + * Create a {@link FusekiServer.Builder} + * initialized according to the command line arguments processed. + */ + public static FusekiServer.Builder builder(String... args) { + return FusekiMain.builder(args); + } + +} 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 8f8cb9991c..1520b16862 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 @@ -118,9 +118,11 @@ public class FusekiServer { /** * Construct a Fuseki server from command line arguments. * The return server has not been started. + * @deprecated Use {@link FusekiMainRunner#construct} or {@link FusekiServerRunner#construct} */ + @Deprecated static public FusekiServer construct(String... args) { - return FusekiMain.build(args); + return FusekiMainRunner.construct(args); } /** Construct a Fuseki server for one dataset. @@ -420,9 +422,17 @@ public class FusekiServer { } catch (Exception e) { throw new FusekiException(e); } } - /** Wait for the server to exit. This call is blocking. */ + /** + * Wait for the server to exit. + * This call starts the server if it has not already been started. + * This call is blocking and does not return unless there is an error. + */ public void join() { - try { server.join(); } + try { + if ( ! server.isStarted() && ! server.isStarting() ) + server.start(); + server.join(); } + catch (FusekiException e) { throw e; } catch (Exception e) { throw new FusekiException(e); } } 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 7a2f85939c..b709b3ab53 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 @@ -28,6 +28,8 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Stream; +import arq.cmdline.CmdARQ; +import arq.cmdline.ModDatasetAssembler; import org.apache.jena.assembler.exceptions.AssemblerException; import org.apache.jena.atlas.io.IOX; import org.apache.jena.atlas.lib.FileOps; @@ -52,9 +54,6 @@ import org.apache.jena.sparql.core.assembler.AssemblerUtils; import org.apache.jena.sys.JenaSystem; import org.slf4j.Logger; -import arq.cmdline.CmdARQ; -import arq.cmdline.ModDatasetAssembler; - public class FusekiMain extends CmdARQ { /** Default HTTP port when running from the command line. */ diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiServerCmd.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiServerCmd.java index 1f4dc87fe7..a5a305099c 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiServerCmd.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiServerCmd.java @@ -18,10 +18,12 @@ package org.apache.jena.fuseki.main.cmds; -import org.apache.jena.fuseki.mod.FusekiServerRunner; +import org.apache.jena.fuseki.main.sys.FusekiModule; +import org.apache.jena.fuseki.server.FusekiServerRunner; import org.apache.jena.fuseki.system.FusekiLogging; -/** Fuseki command that runs a Fuseki server with the admin UI. +/** + * Fuseki command that runs a Fuseki server with the admin UI and other {@link FusekiModule FusekiModules}. * <p> * Use {@code --conf=} for multiple datasets and specific service names. * <p> @@ -45,7 +47,7 @@ public class FusekiServerCmd { * syntax but not start it. */ static public void main(String... args) { - FusekiServerRunner.main(args); + FusekiServerRunner.construct(args).join(); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiServerArgsCustomiser.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiServerArgsCustomiser.java index e3abd58165..275a61877b 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiServerArgsCustomiser.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiServerArgsCustomiser.java @@ -25,8 +25,6 @@ import org.apache.jena.fuseki.main.cmds.FusekiMain; import org.apache.jena.fuseki.main.cmds.ServerArgs; import org.apache.jena.rdf.model.Model; - - /** * Interface to implement for extending the CLI argument parsing portion of a * {@link FusekiServer}. @@ -46,16 +44,16 @@ import org.apache.jena.rdf.model.Model; * {@link FusekiAutoModule#start()} or from Java application code. * </li> * <li> - * {@link #serverArgsModify} — Register or modify the argument setup to be + * {@link #serverArgsModify} – Register or modify the argument setup to be * used to parse the command line. * </li> * <li> - * {@link #serverArgsPrepare} — Called after parsing the command line and + * {@link #serverArgsPrepare} – Called after parsing the command line and * recoding the command line settings in {@link ServerArgs}. Customisers can record * argument values and flags. * </li> * <li> - * {@link #serverArgsBuilder} — Called after the {@link ServerArgs} have + * {@link #serverArgsBuilder} – Called after the {@link ServerArgs} have * been used to construct a server builder. * </li> * </ul> @@ -76,7 +74,7 @@ public interface FusekiServerArgsCustomiser { * The server construction is aborted. * * @param fusekiCmd Fuseki Main command line arguments - * @param serverArgs Intial setting before command line processing. + * @param serverArgs Initial setting before command line processing. */ public default void serverArgsModify(CmdGeneral fusekiCmd, ServerArgs serverArgs) { } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerModules.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerModules.java new file mode 100644 index 0000000000..292e641d65 --- /dev/null +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerModules.java @@ -0,0 +1,42 @@ +/* + * 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 org.apache.jena.fuseki.mod; + +import org.apache.jena.fuseki.main.sys.FusekiModule; +import org.apache.jena.fuseki.main.sys.FusekiModules; +import org.apache.jena.fuseki.mod.admin.FMod_Admin; +import org.apache.jena.fuseki.mod.prometheus.FMod_Prometheus; +import org.apache.jena.fuseki.mod.shiro.FMod_Shiro; +import org.apache.jena.fuseki.mod.ui.FMod_UI; + +public class FusekiServerModules { + + /** A use-once {@link FusekiModules} for the full-featured Fuseki server. */ + public static FusekiModules serverModules() { + // Modules may have state that is carried across the build steps or used for reload. + FusekiModule fmodShiro = FMod_Shiro.create(); + FusekiModule fmodAdmin = FMod_Admin.create(); + FusekiModule fmodUI = FMod_UI.create(); + FusekiModule fmodPrometheus = FMod_Prometheus.create(); + + FusekiModules serverModules = FusekiModules.create(fmodAdmin, fmodUI, fmodShiro, fmodPrometheus); + return serverModules; + } + +} diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java index fc4a158166..c8797c4c22 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java @@ -18,102 +18,38 @@ package org.apache.jena.fuseki.mod; -import java.net.BindException; - -import org.apache.jena.atlas.lib.FileOps; -import org.apache.jena.atlas.lib.Lib; -import org.apache.jena.cmd.CmdGeneral; -import org.apache.jena.fuseki.Fuseki; -import org.apache.jena.fuseki.FusekiException; import org.apache.jena.fuseki.main.FusekiServer; -import org.apache.jena.fuseki.main.cmds.FusekiMain; -import org.apache.jena.fuseki.main.cmds.ServerArgs; -import org.apache.jena.fuseki.main.sys.FusekiModule; import org.apache.jena.fuseki.main.sys.FusekiModules; -import org.apache.jena.fuseki.main.sys.FusekiServerArgsCustomiser; -import org.apache.jena.fuseki.mgt.FusekiServerCtl; -import org.apache.jena.fuseki.mod.admin.FMod_Admin; -import org.apache.jena.fuseki.mod.prometheus.FMod_Prometheus; -import org.apache.jena.fuseki.mod.shiro.FMod_Shiro; -import org.apache.jena.fuseki.mod.ui.FMod_UI; +/** + * @deprecated Use from new locations + */ +@Deprecated(forRemoval = true) public class FusekiServerRunner { - public static void main(String... args) { - prepareFusekiServerConstruct(); - FusekiMain.run(args); - // Does not return. - } - /** * Run {@link FusekiServer} with {@link FusekiModules} as given by {@link #serverModules()}. + * @deprecated Use from new location {@link org.apache.jena.fuseki.server.FusekiServerRunner#runASync}. */ + @Deprecated(forRemoval = true) public static FusekiServer runAsync(String... args) { - FusekiServer server = construct(args); - try { - return server.start(); - } catch (FusekiException ex) { - if ( ex.getCause() instanceof BindException ) { -// if ( serverArgs.jettyConfigFile == null ) -// Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port="+serverArgs.port); -// else -// Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port in use"); - Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port in use"); - System.exit(1); - } - throw ex; - } catch (Exception ex) { - throw new FusekiException("Failed to start server: " + ex.getMessage(), ex); - } + return org.apache.jena.fuseki.server.FusekiServerRunner.runAsync(args); } /** * Build but do not start, a {@link FusekiServer} with {@link FusekiModules} as given by {@link #serverModules()}. + * @deprecated Use from new location {@link org.apache.jena.fuseki.server.FusekiServerRunner#construct}. */ + @Deprecated(forRemoval = true) public static FusekiServer construct(String... args) { - prepareFusekiServerConstruct(); - // Make server - FusekiServer server = FusekiServer.construct(args); - resetFusekiMain(); - return server; - } - - private static void prepareFusekiServerConstruct() { - String fusekiBase = Lib.getenv(FusekiServerCtl.envFusekiBase); - if ( fusekiBase == null ) - fusekiBase = FusekiServerCtl.dftFusekiBase; - FileOps.ensureDir(fusekiBase); - - FusekiModules serverModules = serverModules(); - - // Adjust the default settings of ServerArgs - FusekiServerArgsCustomiser initializeServerArgs = new FusekiServerArgsCustomiser() { - @Override - public void serverArgsModify(CmdGeneral fusekiCmd, ServerArgs serverArgs) { - serverArgs.allowEmpty = true; - serverArgs.fusekiModules = serverModules; - } - }; - - FusekiMain.resetCustomisers(); - FusekiMain.addCustomiser(initializeServerArgs); - // They can also modify the argument processing. - serverModules.forEach(FusekiMain::addCustomiser); - } - - private static void resetFusekiMain() { - FusekiMain.resetCustomisers(); + return org.apache.jena.fuseki.server.FusekiServerRunner.construct(args); } - /** A use-once {@link FusekiModules} for the full-featured Fuseki server. */ + /** + * @deprecated Use from new location {@link org.apache.jena.fuseki.server.FusekiServerModules#serverModules}. + */ + @Deprecated(forRemoval = true) public static FusekiModules serverModules() { - // Modules may have state that is carried across the build steps or used for reload. - FusekiModule fmodShiro = FMod_Shiro.create(); - FusekiModule fmodAdmin = FMod_Admin.create(); - FusekiModule fmodUI = FMod_UI.create(); - FusekiModule fmodPrometheus = FMod_Prometheus.create(); - - FusekiModules serverModules = FusekiModules.create(fmodAdmin, fmodUI, fmodShiro, fmodPrometheus); - return serverModules; + return org.apache.jena.fuseki.mod.FusekiServerModules.serverModules(); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/shiro/FMod_Shiro.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/shiro/FMod_Shiro.java index add556c272..8746846bad 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/shiro/FMod_Shiro.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/shiro/FMod_Shiro.java @@ -70,12 +70,8 @@ public class FMod_Shiro implements FusekiModule { return new FMod_Shiro(); } - // Assumes the whole system is "Shiro". - // No setup? - public static final Logger shiroConfigLog = LoggerFactory.getLogger(Fuseki.PATH + ".Shiro"); - private static List<String> defaultIniFileLocations = List.of("file:shiro.ini", "file:/etc/fuseki/shiro.ini"); private static List<String> iniFileLocations = null; private static ArgDecl argShiroIni = new ArgDecl(true, "shiro", "shiro-ini"); diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/server/FusekiServerRunner.java similarity index 68% copy from jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java copy to jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/server/FusekiServerRunner.java index fc4a158166..30212b4d6c 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiServerRunner.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/server/FusekiServerRunner.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.jena.fuseki.mod; +package org.apache.jena.fuseki.server; import java.net.BindException; @@ -25,28 +25,27 @@ import org.apache.jena.atlas.lib.Lib; import org.apache.jena.cmd.CmdGeneral; import org.apache.jena.fuseki.Fuseki; import org.apache.jena.fuseki.FusekiException; +import org.apache.jena.fuseki.main.FusekiMainRunner; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.cmds.FusekiMain; import org.apache.jena.fuseki.main.cmds.ServerArgs; -import org.apache.jena.fuseki.main.sys.FusekiModule; import org.apache.jena.fuseki.main.sys.FusekiModules; import org.apache.jena.fuseki.main.sys.FusekiServerArgsCustomiser; import org.apache.jena.fuseki.mgt.FusekiServerCtl; -import org.apache.jena.fuseki.mod.admin.FMod_Admin; -import org.apache.jena.fuseki.mod.prometheus.FMod_Prometheus; -import org.apache.jena.fuseki.mod.shiro.FMod_Shiro; -import org.apache.jena.fuseki.mod.ui.FMod_UI; +import org.apache.jena.fuseki.mod.FusekiServerModules; +/** + * Functions for building and runner a {@link FusekiServer} configured from command line arguments + * and system {@link FusekiModules}. + * + * @see {@link FusekiMainRunner} for similar functionality except without the configuring with {@link FusekiModules}. + */ public class FusekiServerRunner { - public static void main(String... args) { - prepareFusekiServerConstruct(); - FusekiMain.run(args); - // Does not return. - } - /** * Run {@link FusekiServer} with {@link FusekiModules} as given by {@link #serverModules()}. + * @param Command line arguments. + * @return Return the running server. */ public static FusekiServer runAsync(String... args) { FusekiServer server = construct(args); @@ -54,10 +53,6 @@ public class FusekiServerRunner { return server.start(); } catch (FusekiException ex) { if ( ex.getCause() instanceof BindException ) { -// if ( serverArgs.jettyConfigFile == null ) -// Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port="+serverArgs.port); -// else -// Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port in use"); Fuseki.serverLog.error("Failed to start server: "+ex.getCause().getMessage()+ ": port in use"); System.exit(1); } @@ -67,15 +62,34 @@ public class FusekiServerRunner { } } + /** + * Run {@link FusekiServer} with {@link FusekiModules} as given by {@link #serverModules()}. + * This function does not return. + */ + public static void run(String... args) { + FusekiServer server = runAsync(args); + server.join(); + } + /** * Build but do not start, a {@link FusekiServer} with {@link FusekiModules} as given by {@link #serverModules()}. */ public static FusekiServer construct(String... args) { + FusekiServer.Builder builder = builder(args); + return builder.build(); + } + + /** + * Create a {@link FusekiServer.Builder} that has the FusekiServer with + * server modules setup and the command line args processed. + */ + public static FusekiServer.Builder builder(String... args) { prepareFusekiServerConstruct(); - // Make server - FusekiServer server = FusekiServer.construct(args); - resetFusekiMain(); - return server; + try { + return FusekiMain.builder(args); + } finally { + resetFusekiMain(); + } } private static void prepareFusekiServerConstruct() { @@ -84,7 +98,7 @@ public class FusekiServerRunner { fusekiBase = FusekiServerCtl.dftFusekiBase; FileOps.ensureDir(fusekiBase); - FusekiModules serverModules = serverModules(); + FusekiModules serverModules = FusekiServerModules.serverModules(); // Adjust the default settings of ServerArgs FusekiServerArgsCustomiser initializeServerArgs = new FusekiServerArgsCustomiser() { @@ -104,16 +118,4 @@ public class FusekiServerRunner { private static void resetFusekiMain() { FusekiMain.resetCustomisers(); } - - /** A use-once {@link FusekiModules} for the full-featured Fuseki server. */ - public static FusekiModules serverModules() { - // Modules may have state that is carried across the build steps or used for reload. - FusekiModule fmodShiro = FMod_Shiro.create(); - FusekiModule fmodAdmin = FMod_Admin.create(); - FusekiModule fmodUI = FMod_UI.create(); - FusekiModule fmodPrometheus = FMod_Prometheus.create(); - - FusekiModules serverModules = FusekiModules.create(fmodAdmin, fmodUI, fmodShiro, fmodPrometheus); - return serverModules; - } } diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java index 8396f202fb..3bd654ade4 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java @@ -24,11 +24,13 @@ import org.junit.platform.suite.api.Suite; import org.apache.jena.fuseki.main.TS_FusekiMain; import org.apache.jena.fuseki.main.access.TS_SecurityFuseki; import org.apache.jena.fuseki.mod.TS_FusekiMods; +import org.apache.jena.fuseki.server.TS_FusekiServer; @Suite @SelectClasses({ TS_FusekiMain.class, TS_SecurityFuseki.class, - TS_FusekiMods.class + TS_FusekiMods.class, + TS_FusekiServer.class }) public class TC_FusekiServer {} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java index 5617b63f9d..a46580678c 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestConfigFile.java @@ -325,7 +325,7 @@ public class TestConfigFile { // Several types of Model. // Requires that the configuration file has had the assembler registrations added correctly. @Test public void setupDatasetOfModels() { - FusekiServer server = FusekiServer.construct("--port=0", "--conf", DIR+"configOfModels.ttl"); + FusekiServer server = FusekiMainRunner.construct("--port=0", "--conf", DIR+"configOfModels.ttl"); server.start(); server.stop(); } diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestCrossOriginFilter.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestCrossOriginFilter.java index 26daae5826..a3702f6eef 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestCrossOriginFilter.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestCrossOriginFilter.java @@ -75,7 +75,7 @@ public class TestCrossOriginFilter { } private static FusekiServer server(String ...args) { - return FusekiServer.construct(args); + return FusekiMainRunner.construct(args); } private static void executeWithServer(FusekiServer server, String datasetName, Consumer<String> action) { @@ -88,7 +88,7 @@ public class TestCrossOriginFilter { @Test public void test_corsWithOrigin() { - FusekiServer server = FusekiServer.construct("-v", "--port=0", "--mem", "/ds"); + FusekiServer server = FusekiMainRunner.construct("-v", "--port=0", "--mem", "/ds"); executeWithServer(server, "/ds", URL->{ // Default responses. String originString = "https://test.example.org/"; @@ -121,7 +121,7 @@ public class TestCrossOriginFilter { @Test public void test_corsLocalhost() { - FusekiServer server = FusekiServer.construct("-v", "--port=0", "--mem", "/ds"); + FusekiServer server = FusekiMainRunner.construct("-v", "--port=0", "--mem", "/ds"); executeWithServer(server, "/ds", URL->{ HttpResponse<InputStream> response = httpOptions(URL, //"Host", "test.example.com" diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TS_FusekiMods.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TS_FusekiMods.java index b8d8ddf482..48c5cb2b2b 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TS_FusekiMods.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TS_FusekiMods.java @@ -18,11 +18,12 @@ package org.apache.jena.fuseki.mod; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; + import org.apache.jena.fuseki.mod.admin.TSMod_Admin; import org.apache.jena.fuseki.mod.metrics.TestModPrometheus; import org.apache.jena.fuseki.mod.shiro.TestModShiro; -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; @Suite @SelectClasses({ @@ -36,8 +37,7 @@ import org.junit.platform.suite.api.Suite; // Shiro TestModShiro.class, - // Whole server - TestFusekiServer.class + // Integrated server tested in TS_FusekiServer.class }) public class TS_FusekiMods { public TS_FusekiMods() {} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/FusekiServerPerTestClass.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/FusekiServerPerTestClass.java index 5f1cbc35c7..fc761b6a9f 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/FusekiServerPerTestClass.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/FusekiServerPerTestClass.java @@ -23,6 +23,9 @@ import static org.junit.jupiter.api.Assertions.fail; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + import org.apache.jena.atlas.lib.FileOps; import org.apache.jena.atlas.logging.LogCtl; import org.apache.jena.fuseki.Fuseki; @@ -30,14 +33,12 @@ import org.apache.jena.fuseki.ctl.ActionSleep; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.sys.FusekiModules; import org.apache.jena.fuseki.mgt.FusekiServerCtl; -import org.apache.jena.fuseki.mod.FusekiServerRunner; +import org.apache.jena.fuseki.mod.FusekiServerModules; import org.apache.jena.fuseki.server.DataAccessPointRegistry; import org.apache.jena.fuseki.system.FusekiLogging; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.DatasetGraphFactory; import org.awaitility.Awaitility; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; /** * Framework for running tests on a Fuseki server, with a single server for all tests. @@ -88,7 +89,7 @@ public class FusekiServerPerTestClass { // For the one-per-class setup, include the usual modules for jena-fuseki-server. private static FusekiModules modulesSetup() { - return FusekiServerRunner.serverModules(); + return FusekiServerModules.serverModules(); } private static FusekiServer createServerForTest() { diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TS_FusekiServer.java similarity index 75% copy from jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java copy to jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TS_FusekiServer.java index 8396f202fb..bc44ce393a 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/TC_FusekiServer.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TS_FusekiServer.java @@ -16,19 +16,15 @@ * limitations under the License. */ -package org.apache.jena.fuseki; +package org.apache.jena.fuseki.server; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; -import org.apache.jena.fuseki.main.TS_FusekiMain; -import org.apache.jena.fuseki.main.access.TS_SecurityFuseki; -import org.apache.jena.fuseki.mod.TS_FusekiMods; - @Suite @SelectClasses({ - TS_FusekiMain.class, - TS_SecurityFuseki.class, - TS_FusekiMods.class + TestFusekiServer.class, + TestFusekiServerCmd.class }) -public class TC_FusekiServer {} + +public class TS_FusekiServer {} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TestFusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServer.java similarity index 94% rename from jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TestFusekiServer.java rename to jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServer.java index 48140e0790..c16eb08f56 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/TestFusekiServer.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServer.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.jena.fuseki.mod; +package org.apache.jena.fuseki.server; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -29,6 +29,7 @@ import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.cmds.FusekiMain; import org.apache.jena.fuseki.main.sys.FusekiModules; import org.apache.jena.fuseki.mgt.FusekiServerCtl; +import org.apache.jena.fuseki.mod.FusekiServerModules; import org.apache.jena.fuseki.system.FusekiLogging; import org.apache.jena.http.HttpOp; @@ -71,7 +72,7 @@ public class TestFusekiServer { String runBase = serverBase+"2"; setup(runBase); // Build-run programmatically. - FusekiModules serverModules = FusekiServerRunner.serverModules(); + FusekiModules serverModules = FusekiServerModules.serverModules(); FusekiServer server = FusekiServer.create().port(0).fusekiModules(serverModules).build(); server.start(); try { diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServerCmd.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServerCmd.java new file mode 100644 index 0000000000..52dd4f6c61 --- /dev/null +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/server/TestFusekiServerCmd.java @@ -0,0 +1,117 @@ +/* + * 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 org.apache.jena.fuseki.server; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.File; +import java.io.IOException; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.apache.commons.io.FileUtils; +import org.apache.jena.atlas.lib.Lib; +import org.apache.jena.fuseki.FusekiConfigException; +import org.apache.jena.fuseki.main.FusekiServer; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; +import org.apache.jena.http.HttpOp; +import org.apache.jena.sparql.exec.http.Params; + +/** + * Tests Fuseki Server run with all features (FMods)from the command line. + */ +public class TestFusekiServerCmd { + + static String basearea = "target/run"; + static { + Lib.setenv("FUSEKI_BASE", basearea); + } + + private static void deleteFusekiDir() throws IOException { + File file = new File(basearea); + if ( file.exists() ) + FileUtils.deleteDirectory(file); + } + + @BeforeAll static void beforeAll() throws IOException { + deleteFusekiDir(); + } + + @BeforeEach void setup() throws IOException { + clearUp(); + } + + @AfterAll static void afterAll() throws IOException { + clearUp(); + } + + static void clearUp() throws IOException { + deleteFusekiDir(); + FusekiServerCtl.clearUpSystemState(); + } + + @Test public void plainStart() { + FusekiServer server = FusekiServerRunner.construct(); + server.start(); + server.stop(); + } + + @Test public void persistentConfigurationBlockCommandLine() { + // Create a persistent configuration. + + String dbName = "/ds93" ; + + FusekiServer server0 = FusekiServerRunner.construct(); + server0.start(); + addDataset(server0, dbName); + server0.stop(); + + // Check run area? + + // Name clash. + assertThrows(FusekiConfigException.class, ()-> start_stop_server("--mem", dbName) ); + + // And no args is fine. + start_stop_server(); + + // Different database + start_stop_server("--mem", "/ds99"); + } + + + private void addDataset(FusekiServer server, String dbName) { + String serverURL = server.serverURL(); + assertNotNull(serverURL); + String actionDataset = serverURL+"$/datasets"; + String datasetURL = server.datasetURL(dbName); + Params params = Params.create().add("dbName", dbName).add("dbType", "mem"); + // Use the template form of adding a dataset.s + HttpOp.httpPostForm(actionDataset, params); + } + + private void start_stop_server(String... args) { + FusekiServer server = FusekiServerRunner.construct(args); + server.start(); + server.stop(); + } +} diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/FusekiArgs.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/FusekiArgs.java index 91c96ad7a4..7078c6806a 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/FusekiArgs.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/cmd/FusekiArgs.java @@ -21,13 +21,12 @@ package org.apache.jena.fuseki.cmd; import java.util.HashMap; import java.util.Map; -import org.apache.jena.fuseki.Fuseki; import org.apache.jena.sparql.core.DatasetGraph; /** Dataset setup (command line, config file) for a dataset (or several if config file) */ public class FusekiArgs { public boolean quiet = false; - public boolean verbose = Fuseki.verboseLogging; + public boolean verbose = false; // Priority order : --conf, templated // through the command line processing should not allow --conf and a templated /dataset.
