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 4f3ca09260ca5ab9888b21454896acf281fec923 Author: Andy Seaborne <[email protected]> AuthorDate: Thu Dec 19 10:44:12 2024 +0000 GH-2902: FusekiServerCtl - Code for server on-disk state --- .../main/java/org/apache/jena/fuseki/Fuseki.java | 1 + .../org/apache/jena/fuseki/build/FusekiConfig.java | 7 +- .../org/apache/jena/fuseki/ctl/ActionMetrics.java | 11 +- .../jena/fuseki/metrics/MetricsProvider.java | 35 ++- .../fuseki/metrics/MetricsProviderRegistry.java | 68 ------ .../PrometheusMetricsProvider.java | 4 +- .../jena/fuseki/metrics/SimpleMetricsProvider.java | 1 - .../fuseki/metrics/prometheus/InitPrometheus.java | 38 ---- .../apache/jena/fuseki/system/DataUploader.java | 2 +- .../jena/fuseki/system/UploadDetailsWithName.java | 32 --- .../apache/jena/fuseki/system/spot/SpotTDB2.java | 1 - .../org.apache.jena.sys.JenaSubsystemLifecycle | 1 - .../org/apache/jena/fuseki/main/FusekiServer.java | 31 ++- .../apache/jena/fuseki/main/cmds/FusekiMain.java | 27 +-- .../jena/fuseki/main/cmds/FusekiServerCmd.java | 5 +- .../jena/fuseki/main/sys/FusekiAutoModules.java | 232 ++++++-------------- .../apache/jena/fuseki/main/sys/FusekiModules.java | 9 +- .../apache/jena/fuseki/mgt/ActionBackupList.java | 6 +- .../org/apache/jena/fuseki/mgt/ActionDatasets.java | 46 +--- .../java/org/apache/jena/fuseki/mgt/Backup.java | 2 +- .../mgt/{FusekiApp.java => FusekiServerCtl.java} | 241 +++++++++++---------- .../org/apache/jena/fuseki/mgt/ServerMgtConst.java | 2 +- .../java/org/apache/jena/fuseki/mgt/Template.java | 2 +- .../apache/jena/fuseki/mod/FusekiModServer.java | 90 ++++++++ .../jena/fuseki/mod/admin/ArgModuleAdmin.java | 4 +- .../apache/jena/fuseki/mod/admin/FMod_Admin.java | 31 ++- .../org/apache/jena/fuseki/mod/package-info.java | 2 - .../jena/fuseki/mod/prometheus/ActionMetrics.java | 49 ----- .../fuseki/mod/prometheus/FMod_Prometheus.java | 15 +- .../apache/jena/fuseki/mod/shiro/FMod_Shiro.java | 10 +- .../org/apache/jena/fuseki/mod/ui/FMod_UI.java | 4 +- .../org/apache/jena/fuseki/server/config.ttl | 2 + .../org/apache/jena/fuseki/TC_FusekiServer.java | 4 +- .../org/apache/jena/fuseki/main/TS_FusekiMain.java | 4 +- .../apache/jena/fuseki/main/TestConfigFile.java | 1 - .../org/apache/jena/fuseki/main/TestMetrics.java | 8 +- ...fixesService.java => PrefixesServiceTests.java} | 3 +- .../apache/jena/fuseki/main/sys/LegacyModule.java | 32 --- .../fuseki/main/sys/ModuleByServiceLoader.java | 1 + .../apache/jena/fuseki/main/sys/ModuleForTest.java | 1 + .../jena/fuseki/main/sys/TestFusekiModules.java | 36 +-- .../org/apache/jena/fuseki/mod/TS_FusekiMods.java | 9 +- .../apache/jena/fuseki/mod/TestFusekiServer.java | 1 - .../jena/fuseki/mod/admin/TS_FusekiServerApp.java | 32 --- .../apache/jena/fuseki/mod/admin/TestAdmin.java | 4 +- .../fuseki/mod/admin/TestTemplateAddDataset.java | 6 +- .../jena/fuseki/mod/metrics/TestModPrometheus.java | 16 +- .../apache/jena/fuseki/mod/shiro/TestModShiro.java | 8 +- .../org.apache.jena.fuseki.main.sys.FusekiModule | 1 - jena-fuseki2/jena-fuseki-server/pom.xml | 10 +- .../jena/fuseki/webapp/FusekiServerListener.java | 8 +- 51 files changed, 492 insertions(+), 704 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 e51b47bdc8..a8c4a0680c 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 @@ -183,6 +183,7 @@ public class Fuseki { public static final String attrOperationRegistry = "org.apache.jena.fuseki:OperationRegistry"; public static final String attrAuthorizationService = "org.apache.jena.fuseki:AuthorizationService"; public static final String attrFusekiServer = "org.apache.jena.fuseki:Server"; + 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-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java index 8496ef7a94..2e6ec3a8ca 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java @@ -189,7 +189,6 @@ public class FusekiConfig { public static List<DataAccessPoint> processServerConfiguration(Graph configuration, Context context) { Node server = findServer(configuration); if ( server != null ) { - // XXX Temporary Resource rServer = resource(configuration, server); mergeContext(configuration,server, context); processLoadClass(configuration,server); @@ -213,8 +212,6 @@ public class FusekiConfig { public static List<DataAccessPoint> processServerConfiguration(Model configuration, Context context) { return processServerConfiguration(configuration.getGraph(), context); } - - // XXX Adapter /*package*/ static Resource resource(Graph graph, Node node) { Model m = ModelFactory.createModelForGraph(graph); RDFNode rNode = m.asRDFNode(node); @@ -271,7 +268,7 @@ public class FusekiConfig { } /** - * Process any {@code ja:loadClass} + * Legacy support for {@code ja:loadClass} */ public static void processLoadClass(Graph configuration, Node server) { if ( server == null ) @@ -633,7 +630,7 @@ public class FusekiConfig { if ( named.size() > 1 ) throw new FusekiConfigException("Multiple property values for <"+FusekiVocabG.pEndpointName+"> with <"+endpointProperty.getURI()+"> for "+BuildLib.displayStr(configuration, svc)); endpointName = named.get(0).getLiteralLexicalForm(); - // XXX Necessary? check + // Check for multiple List<Node> x = G.listSP(configuration, ep, FusekiVocabG.pAllowedUsers); if ( x.size() > 1 ) throw new FusekiConfigException("Multiple fuseki:"+FusekiVocabG.pAllowedUsers.getLocalName()+" for "+displayStr(configuration, ep)); diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionMetrics.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionMetrics.java index d488938e89..8565e8ae73 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionMetrics.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/ctl/ActionMetrics.java @@ -17,7 +17,9 @@ */ package org.apache.jena.fuseki.ctl; -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; +import org.apache.jena.atlas.logging.Log; +import org.apache.jena.fuseki.Fuseki; +import org.apache.jena.fuseki.metrics.MetricsProvider; import org.apache.jena.fuseki.servlets.ActionLib; import org.apache.jena.fuseki.servlets.HttpAction; import org.apache.jena.fuseki.servlets.ServletOps; @@ -42,7 +44,12 @@ public class ActionMetrics extends ActionCtl { @Override public void execute(HttpAction action) { - MetricsProviderRegistry.get().scrape( action ); + MetricsProvider metricsProvider = MetricsProvider.getMetricsProvider(getServletContext()); + if ( metricsProvider == null ) { + Log.warn(Fuseki.actionLog, "No metrics provider"); + ServletOps.errorOccurred("No metrics provider"); + } + metricsProvider.scrape( action ); ServletOps.success(action); } } diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProvider.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProvider.java index 853ed89fd5..2dcd79cea9 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProvider.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProvider.java @@ -17,12 +17,43 @@ */ package org.apache.jena.fuseki.metrics; +import java.util.Objects; + import io.micrometer.core.instrument.MeterRegistry; +import jakarta.servlet.ServletContext; +import org.apache.jena.fuseki.Fuseki; +import org.apache.jena.fuseki.server.DataAccessPointRegistry; import org.apache.jena.fuseki.servlets.HttpAction; +/** Micrometer registry and output generator. */ public interface MetricsProvider { + public MeterRegistry getMeterRegistry(); + public void scrape(HttpAction action); + + /** Bind each data access point in a DataAccessPointRegistry to the system Micrometer {@link MeterRegistry}. */ + public default void dataAccessPointMetrics(MetricsProvider metricsProvider, DataAccessPointRegistry dapRegistry) { + try { + MeterRegistry meterRegistry = metricsProvider.getMeterRegistry(); + if (meterRegistry != null) { + dapRegistry.accessPoints().forEach(dap->{ + new FusekiRequestsMetrics( dap ).bindTo( meterRegistry ); + }); + } + } catch (Throwable th) { + Fuseki.configLog.error("Failed to bind all data access points to netrics provider", th); + } + } - MeterRegistry getMeterRegistry(); - void scrape(HttpAction action); + public static void setMetricsProvider(ServletContext servletContext, MetricsProvider provider) { + Objects.requireNonNull(servletContext); + if ( provider == null ) + servletContext.removeAttribute(Fuseki.attrMetricsProvider); + else + servletContext.setAttribute(Fuseki.attrMetricsProvider, provider); + } + public static MetricsProvider getMetricsProvider(ServletContext servletContext) { + Objects.requireNonNull(servletContext); + return (MetricsProvider)servletContext.getAttribute(Fuseki.attrMetricsProvider); + } } diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProviderRegistry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProviderRegistry.java deleted file mode 100644 index cf37350da7..0000000000 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/MetricsProviderRegistry.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.metrics; - -import io.micrometer.core.instrument.MeterRegistry; -import org.apache.jena.fuseki.Fuseki; -import org.apache.jena.fuseki.server.DataAccessPointRegistry; - -public class MetricsProviderRegistry { - - private static int priority = Integer.MAX_VALUE; - private static MetricsProvider metricsProvider = new SimpleMetricsProvider(); - - public static MetricsProvider get() { - return metricsProvider; - } - - /** @deprecated Use {@link #set(MetricsProvider)} */ - @Deprecated(forRemoval = true) - public static void put(MetricsProvider metricsProvider, int priority) { - if (priority < MetricsProviderRegistry.priority) { - MetricsProviderRegistry.priority = priority; - MetricsProviderRegistry.metricsProvider = metricsProvider; - } - } - - public static void set(MetricsProvider metricsProvider) { - MetricsProviderRegistry.priority = Integer.MAX_VALUE; - MetricsProviderRegistry.metricsProvider = metricsProvider; - } - - /* - * @deprecated Use {@link #dataAccessPointMetrics}. - */ - @Deprecated(forRemoval = true) - public static void bindPrometheus(DataAccessPointRegistry dapRegistry) { - dataAccessPointMetrics(dapRegistry); - } - - /** Bind each data access point in a DataAccessPointRegistry to the system Micrometer {@link MeterRegistry}. */ - public static void dataAccessPointMetrics(DataAccessPointRegistry dapRegistry) { - try { - MeterRegistry meterRegistry = MetricsProviderRegistry.get().getMeterRegistry(); - if (meterRegistry != null) { - dapRegistry.accessPoints().forEach(dap->{ - new FusekiRequestsMetrics( dap ).bindTo( meterRegistry ); - }); - } - } catch (Throwable th) { - Fuseki.configLog.error("Failed to bind all data access points to Prometheus", th); - } - } -} diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/PrometheusMetricsProvider.java similarity index 93% rename from jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java rename to jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/PrometheusMetricsProvider.java index c2cd09e4f2..fd55b74cbc 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/PrometheusMetricsProvider.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/PrometheusMetricsProvider.java @@ -15,14 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.jena.fuseki.metrics.prometheus; +package org.apache.jena.fuseki.metrics; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.prometheusmetrics.PrometheusConfig; import io.micrometer.prometheusmetrics.PrometheusMeterRegistry; import jakarta.servlet.ServletOutputStream; -import org.apache.jena.fuseki.metrics.FusekiMetrics; -import org.apache.jena.fuseki.metrics.MetricsProvider; import org.apache.jena.fuseki.servlets.HttpAction; import org.apache.jena.fuseki.servlets.ServletOps; import org.apache.jena.riot.WebContent; diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/SimpleMetricsProvider.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/SimpleMetricsProvider.java index 6cd62f0699..047ceb6510 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/SimpleMetricsProvider.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/SimpleMetricsProvider.java @@ -76,5 +76,4 @@ public class SimpleMetricsProvider implements MetricsProvider { if ( ! str.endsWith("\n") ) sbuff.append("\n"); } - } diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/InitPrometheus.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/InitPrometheus.java deleted file mode 100644 index 8da041724b..0000000000 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/prometheus/InitPrometheus.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.metrics.prometheus; - -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; -import org.apache.jena.sys.JenaSubsystemLifecycle; - -public class InitPrometheus implements JenaSubsystemLifecycle { - - @Override - public void start() { - MetricsProviderRegistry.set(new PrometheusMetricsProvider()); - } - - @Override - public void stop() { - } - - @Override - public int level() { - return 500; - } -} diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/DataUploader.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/DataUploader.java index df6ae9f57e..33603fa984 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/DataUploader.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/DataUploader.java @@ -105,7 +105,7 @@ public class DataUploader { // Previously, Jena has used HttpServletRequests.getParts. // Each application server (Tomcat and Jetty) has special configuration. - // Use Apache Commons FileUpload as the mulipart parser as it is portable. + // Use Apache Commons FileUpload as the multipart parser as it is portable. /** * Process an HTTP upload of RDF files (triples or quads) with content type diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/UploadDetailsWithName.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/UploadDetailsWithName.java deleted file mode 100644 index 3d60f77a27..0000000000 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/UploadDetailsWithName.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.system; - -import org.apache.jena.sparql.core.DatasetGraph; - -public class UploadDetailsWithName { - public final String graphName; - public final DatasetGraph data; - public final long count; - public UploadDetailsWithName(String gn, DatasetGraph dsg, long parserCount) { - this.graphName = gn; - this.data = dsg; - this.count = parserCount; - } -} diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java index 9e52eb1907..9fc4e416f6 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/system/spot/SpotTDB2.java @@ -172,7 +172,6 @@ class SpotTDB2 { /* * prefixes... */ - // XXX validateBPT(location, params.getPrefixTableBaseName()); validateBPT(location, params.getPrefixTableBaseName()); validateDAT(location, params.getPrefixTableBaseName()+"-data"); diff --git a/jena-fuseki2/jena-fuseki-core/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle b/jena-fuseki2/jena-fuseki-core/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle deleted file mode 100644 index ea05cfe552..0000000000 --- a/jena-fuseki2/jena-fuseki-core/src/main/resources/META-INF/services/org.apache.jena.sys.JenaSubsystemLifecycle +++ /dev/null @@ -1 +0,0 @@ -org.apache.jena.fuseki.metrics.prometheus.InitPrometheus \ No newline at end of file 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 313540ee0e..ac7905a216 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 @@ -52,7 +52,8 @@ import org.apache.jena.fuseki.build.FusekiConfig; import org.apache.jena.fuseki.ctl.*; import org.apache.jena.fuseki.main.cmds.FusekiMain; import org.apache.jena.fuseki.main.sys.*; -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; +import org.apache.jena.fuseki.metrics.MetricsProvider; +import org.apache.jena.fuseki.mod.prometheus.PrometheusMetricsProvider; import org.apache.jena.fuseki.server.*; import org.apache.jena.fuseki.servlets.*; import org.apache.jena.graph.Graph; @@ -1406,17 +1407,19 @@ public class FusekiServer { // FusekiModule call - inspect the DataAccessPointRegistry. FusekiModuleStep.configured(modules, this, dapRegistry, configModel); - // Setup Prometheus metrics. This will become a module. - bindPrometheus(dapRegistry); - - // Process the DataAccessPointRegistry for security. - buildSecurity(dapRegistry); - try { validate(); + // Process the DataAccessPointRegistry for security. + buildSecurity(dapRegistry); + // Build the ServletContextHandler - the Jetty server configuration. ServletContextHandler handler = buildFusekiServerContext(); + handler.getServletContext(); + + // Setup Prometheus metrics. + bindPrometheus(handler.getServletContext(), dapRegistry); + boolean hasFusekiSecurityHandler = applySecurityHandler(handler); // Prepare the DataAccessPointRegistry. // Put it in the servlet context. @@ -1427,8 +1430,6 @@ public class FusekiServer { if ( hasFusekiSecurityHandler ) applyAccessControl(handler, dapRegistry); - - if ( jettyServerConfig != null ) { // Jetty server configuration provided. Server server = jettyServer(handler, jettyServerConfig); @@ -1487,9 +1488,15 @@ public class FusekiServer { return dapRegistry; } - private void bindPrometheus(DataAccessPointRegistry dapRegistry) { - if ( withMetrics ) - MetricsProviderRegistry.dataAccessPointMetrics(dapRegistry); + private void bindPrometheus(ServletContext servletContext, DataAccessPointRegistry dapRegistry) { + if ( withMetrics ) { + MetricsProvider metricProvider = MetricsProvider.getMetricsProvider(servletContext); + if ( metricProvider == null ) { + metricProvider = new PrometheusMetricsProvider(); + MetricsProvider.setMetricsProvider(servletContext, metricProvider); + } + metricProvider.dataAccessPointMetrics(metricProvider, dapRegistry); + } } /** 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 a7a1789c44..bfcf5efda1 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 @@ -38,7 +38,6 @@ import org.apache.jena.fuseki.Fuseki; import org.apache.jena.fuseki.FusekiException; import org.apache.jena.fuseki.main.FusekiMainInfo; import org.apache.jena.fuseki.main.FusekiServer; -import org.apache.jena.fuseki.main.sys.FusekiAutoModules; import org.apache.jena.fuseki.main.sys.FusekiModules; import org.apache.jena.fuseki.main.sys.FusekiServerArgsCustomiser; import org.apache.jena.fuseki.main.sys.InitFusekiMain; @@ -333,7 +332,11 @@ public class FusekiMain extends CmdARQ { private void processStdArguments(Logger log) { - // ---- Definition type + // ---- Command line definition of setup + // One dataset + // or a config file + // or a "standard setup" e.g.SPARQLer + // or empty allowed int numDefinitions = 0; SetupType setup = UNSET; @@ -572,22 +575,12 @@ public class FusekiMain extends CmdARQ { serverArgs.jettyConfigFile = jettyConfigFile; } - boolean withModules = hasValueOfTrue(argEnableModules); - if ( withModules ) { - // Use the discovered ones. - FusekiAutoModules.enable(true); + if ( serverArgs.fusekiModules == null ) { // Allows for external setting of serverArgs.fusekiModules - if ( serverArgs.fusekiModules == null ) { - FusekiAutoModules.setup(); - serverArgs.fusekiModules = FusekiModules.getSystemModules(); - } - } else { - // Disabled module discovery. - FusekiAutoModules.enable(false); - // Allows for external setting of serverArgs.fusekiModules - if ( serverArgs.fusekiModules == null ) { - serverArgs.fusekiModules = FusekiModules.empty(); - } + boolean withModules = hasValueOfTrue(argEnableModules); + serverArgs.fusekiModules = withModules + ? FusekiModules.getSystemModules() + : FusekiModules.empty(); } if ( contains(argCORS) ) { 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 2c61c0ed09..72c121a1c3 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,7 +18,7 @@ package org.apache.jena.fuseki.main.cmds; -import org.apache.jena.fuseki.run.FusekiModServer; +import org.apache.jena.fuseki.mod.FusekiModServer; import org.apache.jena.fuseki.system.FusekiLogging; /** Fuseki command that runs a Fuseki server with the admin UI. @@ -45,9 +45,6 @@ public class FusekiServerCmd { * syntax but not start it. */ static public void main(String... args) { - // Fix up args - // --empty - // --modules=true FusekiModServer.runAsync(args).join(); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiAutoModules.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiAutoModules.java index 5c94e9841b..345755782b 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiAutoModules.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiAutoModules.java @@ -23,12 +23,11 @@ import java.util.Objects; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.function.Function; -import org.apache.jena.atlas.lib.Lib; + import org.apache.jena.atlas.lib.Version; import org.apache.jena.atlas.logging.FmtLog; import org.apache.jena.fuseki.Fuseki; import org.apache.jena.fuseki.FusekiConfigException; -import org.apache.jena.fuseki.main.FusekiServer; import org.slf4j.Logger; /** @@ -39,54 +38,19 @@ public class FusekiAutoModules { private static final Logger LOG = Fuseki.serverLog; private static final Object lock = new Object(); - public static final String logLoadingProperty = "fuseki.logLoading"; - public static final String envLogLoadingProperty = "FUSEKI_LOGLOADING"; - - private static boolean allowDiscovery = true; - private static boolean enabled = true; - - /*package*/ static boolean logModuleLoading() { - return Lib.isPropertyOrEnvVarSetToTrue(logLoadingProperty, envLogLoadingProperty); - } - - /*package*/ static Logger logger() { - return LOG; - } - - /** - * Enable/disable discovery of modules using the service loader. - * The default is 'enabled'. - */ - public static void enable(boolean setting) { - enabled = setting; - } - - /** Whether the system loaded modules are enabled. */ - public static boolean isEnabled() { - return enabled; - } - - /** - * Setup discovery of modules using the service loader. - * This replaces any current setup. - */ - public static void setup() { - if ( ! isEnabled() ) - return; - // Setup and discover now - autoModules = createServiceLoaderModules(); - } - + // Remember last loading. private static FusekiModules currentLoadedModules = null; + // ServiceLoader + private static ServiceLoader<FusekiAutoModule> serviceLoader = null; + /** * Load FusekiAutoModules. This call reloads the modules every call. - * If disabled, return an empty {@link FusekiModules}. */ static FusekiModules load() { - if ( ! enabled ) - return FusekiModules.empty(); - currentLoadedModules = getServiceLoaderModules().load(); + if ( serviceLoader == null ) + serviceLoader = createServiceLoader(); + currentLoadedModules = loadAutoModules(serviceLoader); return get(); } @@ -101,131 +65,79 @@ public class FusekiAutoModules { // -- ServiceLoader machinery. - // testing - /*package*/ static void reset() { - load(); - } - - // Single auto-module controller. - private static FusekiServiceLoaderModules autoModules = null; - - private static FusekiServiceLoaderModules getServiceLoaderModules() { - // Load once. - if ( autoModules == null ) - setup(); - return autoModules; - } - - private static FusekiServiceLoaderModules createServiceLoaderModules() { - FusekiServiceLoaderModules newAutoModules = new FusekiServiceLoaderModules(); - newAutoModules.setDiscovery(); - return newAutoModules; - } +// // testing +// /*package*/ static void reset() { +// load(); +// } /** - * Use {@link java.util.ServiceLoader} to find {@link FusekiModule} - * available via the classpath or modules. - * <p> - * These are the modules used when building a {@link FusekiServer} if - * {@link FusekiServer.Builder#setFusekiModules} is not used. + * Discover FusekiModules via {@link java.util.ServiceLoader}. + * This step does not create the module objects. */ - private static class FusekiServiceLoaderModules { - - // This keeps the list of discovered Fuseki modules. - private ServiceLoader<FusekiAutoModule> serviceLoader = null; - - private FusekiServiceLoaderModules() { } - - private void setDiscovery() { - serviceLoader = discover(); - } - - /** - * Discover FusekiModules via {@link java.util.ServiceLoader}. - * This step does not create the module objects. - */ - private ServiceLoader<FusekiAutoModule> discover() { - // Look for the 4.8.0 name (FusekiModule) which (4.9.0) is split into - // FusekiModule (interface) and FusekiAutoModule (this is loaded by ServiceLoader) - // Remove sometime! - discoveryWarnLegacy(); - - Class<FusekiAutoModule> moduleClass = FusekiAutoModule.class; - ServiceLoader<FusekiAutoModule> newServiceLoader = null; - synchronized (this) { - try { - newServiceLoader = ServiceLoader.load(moduleClass, this.getClass().getClassLoader()); - } catch (ServiceConfigurationError ex) { - FmtLog.error(LOG, ex, "Problem with service loading for %s", moduleClass.getName()); - throw ex; - } - if ( LOG.isDebugEnabled() ) { - newServiceLoader.stream().forEach(provider->{ - FmtLog.info(LOG, "Fuseki Module: %s", provider.type().getSimpleName()); - }); - } - } - return newServiceLoader; - } - - private void discoveryWarnLegacy() { - Class<FusekiModule> moduleClass = FusekiModule.class; + private static ServiceLoader<FusekiAutoModule> createServiceLoader() { + Class<FusekiAutoModule> moduleClass = FusekiAutoModule.class; + ServiceLoader<FusekiAutoModule> newServiceLoader = null; + synchronized (lock) { try { - ServiceLoader<FusekiModule> newServiceLoader = ServiceLoader.load(moduleClass, this.getClass().getClassLoader()); + newServiceLoader = ServiceLoader.load(moduleClass, FusekiAutoModules.class.getClassLoader()); + } catch (ServiceConfigurationError ex) { + FmtLog.error(LOG, ex, "Problem with service loading for %s", moduleClass.getName()); + throw ex; + } + if ( LOG.isDebugEnabled() ) { newServiceLoader.stream().forEach(provider->{ - FmtLog.warn(FusekiAutoModules.class, "Ignored: \"%s\" : legacy use of interface FusekiModule which has changed to FusekiAutoModule", provider.type().getSimpleName()); + FmtLog.info(LOG, "Fuseki Module: %s", provider.type().getSimpleName()); }); - } catch (ServiceConfigurationError ex) { - // Ignore - we were only checking. } } + return newServiceLoader; + } - /** - * Instantiate modules found using the ServiceLoader. - * Each call to {@code load()} creates a new object for the FusekiModule. - * {@code start()} on each module has not been called. - */ - private FusekiModules load() { - if ( serviceLoader == null ) { - FmtLog.error(LOG, "Discovery step has not happened or it failed. Call FusekiSystemModules.discovery before FusekiSystemModules.load()"); - throw new FusekiConfigException("Discovery not performed"); - } - - Function<ServiceLoader.Provider<FusekiAutoModule>, FusekiAutoModule> mapper = provider -> { - try { - FusekiAutoModule afmod = provider.get(); - return afmod; - } catch (ServiceConfigurationError ex) { - FmtLog.error(LOG, ex, - "Error instantiating class %s for %s", provider.type().getName(), FusekiModule.class.getName()); - return null; - } - }; - - // Create auto-module object, skip loads in error, sort auto-modules into level order. - List<FusekiAutoModule> autoMods = serviceLoader.stream() - .map(mapper) - .filter(Objects::nonNull) - .sorted((x,y)-> Integer.compare(x.level(), y.level())) - .toList(); - // Start, and convert to FusekiModules (generics issue) - List<FusekiModule> fmods = autoMods.stream().map(afmod->{ - afmod.start(); - return (FusekiModule)afmod; - }).toList(); - - fmods.forEach(m->{ - String name = m.name(); - if ( name == null ) - name = m.getClass().getSimpleName(); - String verStr = Version.versionForClass(m.getClass()).orElse(null); - if ( verStr == null ) - FmtLog.info(LOG, "Module: %s", name); - else - FmtLog.info(LOG, "Module: %s (%s)", name, verStr); - }); - - return FusekiModules.create(fmods); + /** + * Instantiate modules found using a ServiceLoader. + * Each call to {@code load()} creates a new object for the FusekiModule. + * {@code start()} on each module has not been called. + */ + private static FusekiModules loadAutoModules(ServiceLoader<FusekiAutoModule> serviceLoader) { + if ( serviceLoader == null ) { + FmtLog.error(LOG, "Discovery step has not happened or it failed. Call FusekiSystemModules.discovery before FusekiSystemModules.load()"); + throw new FusekiConfigException("Discovery not performed"); } + + Function<ServiceLoader.Provider<FusekiAutoModule>, FusekiAutoModule> mapper = provider -> { + try { + FusekiAutoModule afmod = provider.get(); + return afmod; + } catch (ServiceConfigurationError ex) { + FmtLog.error(LOG, ex, + "Error instantiating class %s for %s", provider.type().getName(), FusekiModule.class.getName()); + return null; + } + }; + + // Create auto-module object, skip loads in error, sort auto-modules into level order. + List<FusekiAutoModule> autoMods = serviceLoader.stream() + .map(mapper) + .filter(Objects::nonNull) + .sorted((x,y)-> Integer.compare(x.level(), y.level())) + .toList(); + // Start, and convert to FusekiModules (generics issue) + List<FusekiModule> fmods = autoMods.stream().map(afmod->{ + afmod.start(); + return (FusekiModule)afmod; + }).toList(); + + fmods.forEach(m->{ + String name = m.name(); + if ( name == null ) + name = m.getClass().getSimpleName(); + String verStr = Version.versionForClass(m.getClass()).orElse(null); + if ( verStr == null ) + FmtLog.info(LOG, "Module: %s", name); + else + FmtLog.info(LOG, "Module: %s (%s)", name, verStr); + }); + + return FusekiModules.create(fmods); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java index 8075d644d2..5d0d524de8 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java @@ -50,6 +50,11 @@ public class FusekiModules { } public static FusekiModules getSystemModules() { + if ( systemFusekiModules == null ) { + if ( autoLoadedFusekiModules == null ) + autoLoadedFusekiModules = FusekiAutoModules.get(); + systemFusekiModules = autoLoadedFusekiModules; + } return systemFusekiModules; } @@ -78,10 +83,6 @@ public class FusekiModules { return new FusekiModules(modules); } -// public static FusekiModules autoloadedModules() { -// return FusekiAutoModules.load(); -// } - private final List<FusekiModule> modules; private FusekiModules(FusekiModule ... modules) { diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java index 1e52a65b69..f7d0fc446a 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java @@ -66,11 +66,11 @@ public class ActionBackupList extends ActionCtl { }; private JsonValue description(HttpAction action) { - if ( ! Files.isDirectory(FusekiApp.dirBackups) ) - ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiApp.dirBackups)); + if ( ! Files.isDirectory(FusekiServerCtl.dirBackups) ) + ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiServerCtl.dirBackups)); List<Path> paths = new ArrayList<>(); - try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiApp.dirBackups, filterVisibleFiles)) { + try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiServerCtl.dirBackups, filterVisibleFiles)) { stream.forEach(paths::add); } catch (IOException ex) { action.log.error(format("[%d] Backup file list :: IOException :: %s", action.id, ex.getMessage())); diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java index 7630b8c6f0..977bcfea69 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java @@ -140,7 +140,7 @@ public class ActionDatasets extends ActionContainerItem { // ---- // Keep a persistent copy immediately. This is not used for // anything other than being "for the record". - systemFileCopy = FusekiApp.dirSystemFileArea.resolve(uuid.toString()).toString(); + systemFileCopy = FusekiServerCtl.dirSystemFileArea.resolve(uuid.toString()).toString(); try ( OutputStream outCopy = IO.openOutputFile(systemFileCopy) ) { RDFDataMgr.write(outCopy, descriptionModel, Lang.TURTLE); } @@ -186,8 +186,8 @@ public class ActionDatasets extends ActionContainerItem { action.log.info(format("[%d] Create database : name = %s", action.id, datasetPath)); - configFile = FusekiApp.generateConfigurationFilename(datasetPath); - List<String> existing = FusekiApp.existingConfigurationFile(datasetPath); + configFile = FusekiServerCtl.generateConfigurationFilename(datasetPath); + List<String> existing = FusekiServerCtl.existingConfigurationFile(datasetPath); if ( ! existing.isEmpty() ) ServletOps.error(HttpSC.CONFLICT_409, "Configuration file for '"+datasetPath+"' already exists"); @@ -318,7 +318,7 @@ public class ActionDatasets extends ActionContainerItem { // Find the configuration. String filename = name.startsWith("/") ? name.substring(1) : name; - List<String> configurationFiles = FusekiApp.existingConfigurationFile(filename); + List<String> configurationFiles = FusekiServerCtl.existingConfigurationFile(filename); if ( configurationFiles.isEmpty() ) { // ---- Unmanaged @@ -352,7 +352,7 @@ public class ActionDatasets extends ActionContainerItem { boolean isTDB1 = org.apache.jena.tdb1.sys.TDBInternal.isTDB1(dataService.getDataset()); boolean isTDB2 = org.apache.jena.tdb2.sys.TDBInternal.isTDB2(dataService.getDataset()); - // TODO This occasionally fails in tests due to outstanding transactions. + // This occasionally fails in tests due to outstanding transactions. try { dataService.shutdown(); } catch (JenaException ex) { @@ -363,7 +363,7 @@ public class ActionDatasets extends ActionContainerItem { // Delete databases created by the UI, or the admin operation, which are // in predictable, unshared location on disk. // There may not be any database files, the in-memory case. - Path pDatabase = FusekiApp.dirDatabases.resolve(filename); + Path pDatabase = FusekiServerCtl.dirDatabases.resolve(filename); if ( Files.exists(pDatabase)) { try { if ( Files.isSymbolicLink(pDatabase)) { @@ -411,7 +411,7 @@ public class ActionDatasets extends ActionContainerItem { params.put(Template.NAME, dbName.substring(1)); else params.put(Template.NAME, dbName); - FusekiApp.addGlobals(params); + FusekiServerCtl.addGlobals(params); //action.log.info(format("[%d] Create database : name = %s, type = %s", action.id, dbName, dbType )); @@ -430,36 +430,6 @@ public class ActionDatasets extends ActionContainerItem { DataUploader.incomingData(action, dest); } - // [ADMIN] -// // Persistent state change. -// private static void setDatasetState(String name, Resource newState) { -// boolean committed = false; -// system.begin(ReadWrite.WRITE); -// try { -// String dbName = name; -// if ( dbName.startsWith("/") ) -// dbName = dbName.substring(1); -// -// String update = StrUtils.strjoinNL -// (PREFIXES, -// "DELETE { GRAPH ?g { ?s fu:status ?state } }", -// "INSERT { GRAPH ?g { ?s fu:status "+FmtUtils.stringForRDFNode(newState)+" } }", -// "WHERE {", -// " GRAPH ?g { ?s fu:name '"+dbName+"'; ", -// " fu:status ?state .", -// " }", -// "}" -// ); -// UpdateRequest req = UpdateFactory.create(update); -// UpdateAction.execute(req, system); -// system.commit(); -// committed = true; -// } finally { -// if ( ! committed ) system.abort(); -// system.end(); -// } -// } - // ---- Auxiliary functions private static Quad getOne(DatasetGraph dsg, Node g, Node s, Node p, Node o) { @@ -482,8 +452,6 @@ public class ActionDatasets extends ActionContainerItem { return stmt; } - // TODO Merge with Upload.incomingData - private static void bodyAsGraph(HttpAction action, StreamRDF dest) { HttpServletRequest request = action.getRequest(); String base = ActionLib.wholeRequestURL(request); diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Backup.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Backup.java index 70ea5f5156..ea661c7ae6 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Backup.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Backup.java @@ -54,7 +54,7 @@ public class Backup String timestamp = DateTimeUtils.nowAsString("yyyy-MM-dd_HH-mm-ss"); String filename = ds + "_" + timestamp; - filename = FusekiApp.dirBackups.resolve(filename).toString(); + filename = FusekiServerCtl.dirBackups.resolve(filename).toString(); return filename; } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiApp.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiServerCtl.java similarity index 77% rename from jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiApp.java rename to jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiServerCtl.java index d6cd0dc570..3710157122 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiApp.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/FusekiServerCtl.java @@ -56,24 +56,33 @@ import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.assembler.AssemblerUtils; import org.apache.jena.system.G; -public class FusekiApp { +public class FusekiServerCtl { + /** + * Root of the varying files in this deployment. Often $PWD/run. + * This location must be writable. + */ + public static Path FUSEKI_BASE = null; + + public static final String DFT_SHIRO_INI = "shiro.ini"; + public static final String envFusekiBase = "FUSEKI_BASE"; + public static final String envFusekiShiro = "FUSEKI_SHIRO"; + // Relative names of directories in the FUSEKI_BASE area. - public static final String databasesLocationBase = "databases"; + private static final String databasesLocationBase = "databases"; // Place to put Lucene text and spatial indexes. - //private static final String databaseIndexesDir = "indexes"; + private static final String databaseIndexesDir = "text_indexes"; - public static final String backupDirNameBase = "backups"; - public static final String configDirNameBase = "configuration"; - public static final String logsNameBase = "logs"; - public static final String systemFileAreaBase = "system_files"; - public static final String templatesNameBase = "templates"; - public static final String DFT_SHIRO_INI = "shiro.ini"; - public static final String DFT_CONFIG = "config.ttl"; + private static final String backupDirNameBase = "backups"; + private static final String configDirNameBase = "configuration"; + private static final String logsNameBase = "logs"; + private static final String systemFileAreaBase = "system_files"; + private static final String templatesNameBase = "templates"; + private static final String DFT_CONFIG = "config.ttl"; - private static int BaseFusekiAutoModuleLevel = 500; - public static int levelFModAdmin = BaseFusekiAutoModuleLevel; - public static int levelFModUI = BaseFusekiAutoModuleLevel+10; - public static int levelFModShiro = BaseFusekiAutoModuleLevel+20; + private static int BaseFusekiAutoModuleLevel = 500; + public static int levelFModAdmin = BaseFusekiAutoModuleLevel; + public static int levelFModUI = BaseFusekiAutoModuleLevel+10; + public static int levelFModShiro = BaseFusekiAutoModuleLevel+20; /** Directory for TDB databases - this is known to the assembler templates */ @@ -88,9 +97,6 @@ public class FusekiApp { /** Directory for assembler files */ public static Path dirLogs = null; -// /** Directory for system database */ -// public static Path dirSystemDatabase = null; - /** Directory for files uploaded (e.g upload assembler descriptions); not data uploads. */ public static Path dirSystemFileArea = null; @@ -101,24 +107,51 @@ public class FusekiApp { // Marks the end of successful initialization. /*package*/static boolean serverInitialized = false; - - -// /** +// /** OLD // * Root of the Fuseki installation for fixed files. // * This may be null (e.g. running inside a web application container) // */ // public static Path FUSEKI_HOME = null; - /** - * Root of the varying files in this deployment. Often $PWD/run. - * This must be writable. - */ - public static Path FUSEKI_BASE = set_FUSEKI_BASE(); + // Too much is done with statics, assuming one server+admin process + // At the moment, it is one setup happening at a time. + // Once created, it is independent. + // Better, less statics, more FusekiServerApp instance object. + // Current limitation: FUSEKI_BASE is static and set in + // FusekiApp.java line 275 + // ArgModuleAdmin.java line 61 + // FMod_Admin.java line 117 + // FMod_UI.java line 133 + // Template.java line 27 + // ActionDadasets uses addGlobals. + + // Default - "run" in the current directory. + public static final String dftFusekiBase = "run"; + + public FusekiServerCtl(String location) { + if ( location == null ) { + FUSEKI_BASE = null; + return; + } + FUSEKI_BASE = Path.of(location); + } - public static String envFusekiBase = "FUSEKI_BASE"; - public static String envFusekiShiro = "FUSEKI_SHIRO"; + public Path setup() { + // Set the location of the BASE area + setFusekiBase(); + // Ensure the BASE area exists on disk. + setBaseAreaOnDisk(); + // Format the BASE area. + ensureBaseArea(FUSEKI_BASE); + return FUSEKI_BASE; + } - private static Path set_FUSEKI_BASE() { + private void setFusekiBase() { + if ( FUSEKI_BASE == null ) + FUSEKI_BASE = select_FUSEKI_BASE(); + } + + private Path select_FUSEKI_BASE() { // Does not guarantee existence Path setting = null; if ( FUSEKI_BASE == null ) @@ -127,20 +160,14 @@ public class FusekiApp { return setting; } - private static Path calc_FUSEKI_BASE() { + private Path calc_FUSEKI_BASE() { String valueFusekiBase = getenv("FUSEKI_BASE"); if ( valueFusekiBase == null ) valueFusekiBase = dftFusekiBase; return Path.of(valueFusekiBase); } - // Default - "run" in the current directory. - public static final String dftFusekiBase = "run"; - - static void setEnvironment() { - if ( FUSEKI_BASE == null ) - FUSEKI_BASE = set_FUSEKI_BASE(); - + private void setBaseAreaOnDisk() { FmtLog.info(Fuseki.configLog, "FUSEKI_BASE=%s", FUSEKI_BASE); if ( ! Files.exists(FUSEKI_BASE) ) { try { @@ -152,96 +179,44 @@ public class FusekiApp { // Further checks in ensureBaseArea } - public static Path setup() { - // Command line arguments "--base" ... - setEnvironment(); - // Format the BASE area. - FusekiApp.ensureBaseArea(FUSEKI_BASE); - return FUSEKI_BASE; - } - /** * Create directories if found to be missing. */ - public static void ensureBaseArea(Path FUSEKI_BASE) { - if ( Files.exists(FUSEKI_BASE) ) { - if ( ! Files.isDirectory(FUSEKI_BASE) ) - throw new FusekiConfigException("FUSEKI_BASE is not a directory: "+FUSEKI_BASE); - if ( ! Files.isWritable(FUSEKI_BASE) ) - throw new FusekiConfigException("FUSEKI_BASE is not writable: "+FUSEKI_BASE); + private void ensureBaseArea(Path baseArea) { + if ( Files.exists(baseArea) ) { + if ( ! Files.isDirectory(baseArea) ) + throw new FusekiConfigException("FUSEKI_BASE is not a directory: "+baseArea); + if ( ! Files.isWritable(baseArea) ) + throw new FusekiConfigException("FUSEKI_BASE is not writable: "+baseArea); } else { - ensureDir(FUSEKI_BASE); + ensureDir(baseArea); } // Ensure FUSEKI_BASE has the assumed directories. - dirTemplates = writeableDirectory(FUSEKI_BASE, templatesNameBase); - dirDatabases = writeableDirectory(FUSEKI_BASE, databasesLocationBase); - dirBackups = writeableDirectory(FUSEKI_BASE, backupDirNameBase); - dirConfiguration = writeableDirectory(FUSEKI_BASE, configDirNameBase); - dirLogs = writeableDirectory(FUSEKI_BASE, logsNameBase); - dirSystemFileArea = writeableDirectory(FUSEKI_BASE, systemFileAreaBase); + dirTemplates = writeableDirectory(baseArea, templatesNameBase); + dirDatabases = writeableDirectory(baseArea, databasesLocationBase); + dirBackups = writeableDirectory(baseArea, backupDirNameBase); + dirConfiguration = writeableDirectory(baseArea, configDirNameBase); + dirLogs = writeableDirectory(baseArea, logsNameBase); + dirSystemFileArea = writeableDirectory(baseArea, systemFileAreaBase); // ---- Initialize with files. // // Copy missing files into FUSEKI_BASE // Interacts with FMod_Shiro. - if ( Lib.getenv(FusekiApp.envFusekiShiro) == null ) { - copyFileIfMissing(null, DFT_SHIRO_INI, FUSEKI_BASE); - System.setProperty(FusekiApp.envFusekiShiro, FUSEKI_BASE.resolve(DFT_SHIRO_INI).toString()); + if ( Lib.getenv(FusekiServerCtl.envFusekiShiro) == null ) { + copyFileIfMissing(null, DFT_SHIRO_INI, baseArea); + System.setProperty(FusekiServerCtl.envFusekiShiro, baseArea.resolve(DFT_SHIRO_INI).toString()); } - copyFileIfMissing(null, DFT_CONFIG, FUSEKI_BASE); + copyFileIfMissing(null, DFT_CONFIG, baseArea); for ( String n : Template.templateNames ) { - copyFileIfMissing(null, n, FUSEKI_BASE); + copyFileIfMissing(null, n, baseArea); } serverInitialized = true; } - /** Copy a file from src to dst under name fn. - * If src is null, try as a classpath resource - * @param src Source directory, or null meaning use java resource. - * @param fn File name, a relative path. - * @param dst Destination directory. - * - */ - private static void copyFileIfMissing(Path src, String fn, Path dst) { - // fn may be a path. - Path dstFile = dst.resolve(fn); - if ( Files.exists(dstFile) ) - return; - if ( src != null ) { - Path srcFile = src.resolve(fn); - if ( ! Files.exists(dstFile) ) - throw new FusekiConfigException("File not found: "+srcFile); - try { - IOX.safeWrite(dstFile, output->Files.copy(srcFile, output)); - } catch (RuntimeIOException e) { - throw new FusekiConfigException("Failed to copy file "+srcFile+" to "+dstFile, e); - } - } else { - copyFileFromResource(fn, dstFile); - } - } - - private static void copyFileFromResource(String fn, Path dstFile) { - try { - // Get from the file from area "org/apache/jena/fuseki/server" - String absName = "org/apache/jena/fuseki/server/"+fn; - InputStream input = FusekiApp.class - // Else prepends classname as path - .getClassLoader() - .getResourceAsStream(absName); - - if ( input == null ) - throw new FusekiConfigException("Failed to find resource '"+absName+"'"); - IOX.safeWrite(dstFile, (output)-> input.transferTo(output)); - } - catch (RuntimeException e) { - throw new FusekiConfigException("Failed to copy "+fn+" to "+dstFile, e); - } - } - private static List<DataAccessPoint> processServerConfigFile(String configFilename) { if ( ! FileOps.exists(configFilename) ) { Fuseki.configLog.warn("Configuration file '" + configFilename+"' does not exist"); @@ -255,7 +230,7 @@ public class FusekiApp { return x; } - private static DataAccessPoint configFromTemplate(String templateFile, String datasetPath, + private DataAccessPoint configFromTemplate(String templateFile, String datasetPath, boolean allowUpdate, Map<String, String> params) { // ---- Setup if ( params == null ) { @@ -308,6 +283,50 @@ public class FusekiApp { // params.put("FUSEKI_HOME", pathStringOrElse(FusekiAppEnv.FUSEKI_HOME, "unset")); } + /** Copy a file from src to dst under name fn. + * If src is null, try as a classpath resource + * @param src Source directory, or null meaning use java resource. + * @param fn File name, a relative path. + * @param dst Destination directory. + * + */ + private static void copyFileIfMissing(Path src, String fn, Path dst) { + // fn may be a path. + Path dstFile = dst.resolve(fn); + if ( Files.exists(dstFile) ) + return; + if ( src != null ) { + Path srcFile = src.resolve(fn); + if ( ! Files.exists(dstFile) ) + throw new FusekiConfigException("File not found: "+srcFile); + try { + IOX.safeWrite(dstFile, output->Files.copy(srcFile, output)); + } catch (RuntimeIOException e) { + throw new FusekiConfigException("Failed to copy file "+srcFile+" to "+dstFile, e); + } + } else { + copyFileFromResource(fn, dstFile); + } + } + + private static void copyFileFromResource(String fn, Path dstFile) { + try { + // Get from the file from area "org/apache/jena/fuseki/server" + String absName = "org/apache/jena/fuseki/server/"+fn; + InputStream input = FusekiServerCtl.class + // Else prepends classname as path + .getClassLoader() + .getResourceAsStream(absName); + + if ( input == null ) + throw new FusekiConfigException("Failed to find resource '"+absName+"'"); + IOX.safeWrite(dstFile, (output)-> input.transferTo(output)); + } + catch (RuntimeException e) { + throw new FusekiConfigException("Failed to copy "+fn+" to "+dstFile, e); + } + } + private static String pathStringOrElse(Path path, String dft) { if ( path == null ) return dft; @@ -405,7 +424,7 @@ public class FusekiApp { // Without "/" if ( filename.startsWith("/")) filename = filename.substring(1); - Path p = FusekiApp.dirConfiguration.resolve(filename+".ttl"); + Path p = FusekiServerCtl.dirConfiguration.resolve(filename+".ttl"); return p.toString(); } @@ -413,12 +432,12 @@ public class FusekiApp { public static List<String> existingConfigurationFile(String baseFilename) { try { List<String> paths = new ArrayList<>(); - try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiApp.dirConfiguration, baseFilename+".*") ) { - stream.forEach((p)-> paths.add(FusekiApp.dirConfiguration.resolve(p).toString() )); + try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiServerCtl.dirConfiguration, baseFilename+".*") ) { + stream.forEach((p)-> paths.add(FusekiServerCtl.dirConfiguration.resolve(p).toString() )); } return paths; } catch (IOException ex) { - throw new InternalErrorException("Failed to read configuration directory "+FusekiApp.dirConfiguration); + throw new InternalErrorException("Failed to read configuration directory "+FusekiServerCtl.dirConfiguration); } } diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java index 056b161470..c67aa547d1 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/ServerMgtConst.java @@ -20,7 +20,7 @@ package org.apache.jena.fuseki.mgt; /** * Various constants used in the management API functions and JSON responses in the - * webapp/full server. + * Fuseki server app. */ public class ServerMgtConst { public static final String opDatasets = "datasets"; diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Template.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Template.java index 2ef63652b8..1266fb3faf 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Template.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mgt/Template.java @@ -24,7 +24,7 @@ import java.nio.file.Path; public class Template { public static Path getPath(String templateName) { - return FusekiApp.FUSEKI_BASE.resolve(templateName); + return FusekiServerCtl.FUSEKI_BASE.resolve(templateName); } public static final String templateDir = "templates"; diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiModServer.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiModServer.java new file mode 100644 index 0000000000..99bd550b4f --- /dev/null +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/FusekiModServer.java @@ -0,0 +1,90 @@ +/* + * 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.jena.atlas.lib.FileOps; +import org.apache.jena.fuseki.main.FusekiServer; +import org.apache.jena.fuseki.main.cmds.FusekiMain; +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 FusekiModServer { + + public static void main(String... args) { + runAsync(args).join(); + } + + public static FusekiServer runAsync(String... args) { + return construct(args).start(); + } + + public static FusekiServer construct(String... args) { + // Order: FMod_Admin before FMod_Shiro + // These modules may have state that is carried across the build steps. + FusekiModule fmodShiro = FMod_Shiro.create(); + FusekiModule fmodAdmin = FMod_Admin.create(); + + FusekiModules serverModules = FusekiModules.create( fmodAdmin + , FMod_UI.get() + , fmodShiro + , FMod_Prometheus.get() ); + serverModules.forEach(FusekiMain::addCustomiser); + + System.setProperty("FUSEKI_BASE", "run"); + FileOps.ensureDir("run"); + + // Adjust args. + List<String> argList = Arrays.asList(args); + // Ensure "--empty", "--modules=true" + // Better?: moded startup - i.e. setting defaults. + + if ( args.length == 0 ) { + String [] defaultArgs = { "--port=3030", "--empty" }; + args = defaultArgs; + } else { + List<String> argsList = new ArrayList<String>(Arrays.asList(args)); + if ( ! containsArg(argList, "--?empty") ) + argsList.add(0, "--empty"); // addFirst in java21 + if ( ! containsArg(argList, "--?modules") ) + argsList.add(0, "--modules=true"); + args = argsList.toArray(args); + } + + FusekiModules modules = serverModules; + FusekiModules.setSystemDefault(modules); + FusekiServer server = FusekiServer.construct(args); + return server; + } + + private static boolean containsArg(List<String> argList, String argRegex) { + //Pattern pattern = Pattern.compile(argRegex); + + return argList.stream().anyMatch(arg->{ + return arg.matches(argRegex); + }); + } +} diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/ArgModuleAdmin.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/ArgModuleAdmin.java index 6cb3ed0b4e..f1b9d6c751 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/ArgModuleAdmin.java +++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/admin/ArgModuleAdmin.java @@ -26,7 +26,7 @@ import org.apache.jena.cmd.ArgModuleGeneral; import org.apache.jena.cmd.CmdArgModule; import org.apache.jena.cmd.CmdGeneral; import org.apache.jena.fuseki.FusekiConfigException; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; public class ArgModuleAdmin implements ArgModuleGeneral { // Add a static of "extra command" @@ -58,7 +58,7 @@ public class ArgModuleAdmin implements ArgModuleGeneral { if ( ! Files.isWritable(directory) ) throw new FusekiConfigException("Not writable: "+dirStr); - FusekiApp.FUSEKI_BASE = directory; + FusekiServerCtl.FUSEKI_BASE = directory; } @Override 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 c48bd290bb..d4ea62e661 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 @@ -38,7 +38,7 @@ import org.apache.jena.fuseki.main.sys.FusekiModule; import org.apache.jena.fuseki.mgt.ActionBackup; import org.apache.jena.fuseki.mgt.ActionBackupList; import org.apache.jena.fuseki.mgt.ActionDatasets; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.fuseki.server.DataAccessPoint; import org.apache.jena.rdf.model.Model; import org.slf4j.Logger; @@ -80,8 +80,8 @@ public class FMod_Admin implements FusekiModule { ArgModuleGeneral argModule = new ArgModuleGeneral() { @Override public void registerWith(CmdGeneral cmdLine) { - cmdLine.add(argAdmin, "--admin", "Enable server admin with user:password"); - cmdLine.add(argAdminArea,"--adminRun", "Directory for server configuration"); +// cmdLine.add(argAdmin, "--admin", "Enable server admin with user:password"); +// cmdLine.add(argAdminArea,"--adminRun", "Directory for server configuration"); } @Override public void processArgs(CmdArgModule cmdLine) {} @@ -101,6 +101,7 @@ public class FMod_Admin implements FusekiModule { if ( dirStr != null ) directory = Path.of(dirStr); + // Phase 2 if ( admin.equals("localhost") ) {} else { String pwFile = admin; @@ -113,7 +114,7 @@ public class FMod_Admin implements FusekiModule { if ( ! Files.isWritable(directory) ) throw new FusekiConfigException("Not writable: "+dirStr); } - FusekiApp.FUSEKI_BASE = directory; + FusekiServerCtl.FUSEKI_BASE = directory; } // @Override @@ -124,28 +125,26 @@ public class FMod_Admin implements FusekiModule { @Override public void prepare(FusekiServer.Builder builder, Set<String> datasetNames, Model configModel) { - // Unpack + // Ensure the work area is setup - // XXX Do better! - FusekiApp.FUSEKI_BASE = null; - -// FusekiApp fusekiApp = new FusekiApp(); -// //fusekiApp.init(); -// String fusekiApp.FUSEKI_BASE - - Path path = FusekiApp.setup(); + Path path; + synchronized(FusekiServerCtl.class) { + // Temporary - one at a time because FUSEKI_BASE is static. + FusekiServerCtl app = new FusekiServerCtl(null); + path = app.setup(); + } FmtLog.info(LOG, "Fuseki Admin: %s", path); // Shiro. - Path shiroIni = path.resolve(FusekiApp.DFT_SHIRO_INI); + Path shiroIni = path.resolve(FusekiServerCtl.DFT_SHIRO_INI); if ( Files.exists(shiroIni) ) { - System.setProperty(FusekiApp.envFusekiShiro, shiroIni.toString()); + System.setProperty(FusekiServerCtl.envFusekiShiro, shiroIni.toString()); } else { FmtLog.info(LOG, "No shiro.ini: dir=%s", path); } - String configDir = FusekiApp.dirConfiguration.toString(); + String configDir = FusekiServerCtl.dirConfiguration.toString(); List<DataAccessPoint> directoryDatabases = FusekiConfig.readConfigurationDirectory(configDir); if ( directoryDatabases.isEmpty() ) diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/package-info.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/package-info.java deleted file mode 100644 index 7345d58a49..0000000000 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -package org.apache.jena.fuseki.mod; - diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/ActionMetrics.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/ActionMetrics.java deleted file mode 100644 index 92164563a6..0000000000 --- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/mod/prometheus/ActionMetrics.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * 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.prometheus; - -import org.apache.jena.fuseki.ctl.ActionCtl; -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; -import org.apache.jena.fuseki.servlets.ActionLib; -import org.apache.jena.fuseki.servlets.HttpAction; -import org.apache.jena.fuseki.servlets.ServletOps; - -public class ActionMetrics extends ActionCtl { - - public ActionMetrics() { super(); } - - @Override - public void execGet(HttpAction action) { - super.executeLifecycle(action); - } - - @Override - public void execOptions(HttpAction action) { - ActionLib.doOptionsGet(action); - ServletOps.success(action); - } - - @Override - public void validate(HttpAction action) {} - - @Override - public void execute(HttpAction action) { - MetricsProviderRegistry.get().scrape( action ); - ServletOps.success(action); - } -} 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 0d51e0bd4f..c61a45fc05 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 @@ -20,9 +20,11 @@ package org.apache.jena.fuseki.mod.prometheus; import java.util.Set; +import org.apache.jena.fuseki.Fuseki; +import org.apache.jena.fuseki.ctl.ActionMetrics; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.sys.FusekiModule; -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; +import org.apache.jena.fuseki.metrics.MetricsProvider; import org.apache.jena.rdf.model.Model; /** @@ -42,22 +44,19 @@ public class FMod_Prometheus implements FusekiModule { // @Override // public int level() { // return 5000; -// } -// -// @Override public void start() { -// Fuseki.configLog.info("FMod Prometheus Metrics"); -// MetricsProviderRegistry.set(new PrometheusMetricsProvider()); // } @Override public String name() { return "FMod Prometheus Metrics"; } @Override public void prepare(FusekiServer.Builder serverBuilder, Set<String> datasetNames, Model configModel) { - //MetricsProviderRegistry.set(new PrometheusMetricsProvider()); + MetricsProvider metricsProvider = new PrometheusMetricsProvider(); + serverBuilder.addServletAttribute(Fuseki.attrMetricsProvider, metricsProvider); serverBuilder.addServlet("/$/metrics", new ActionMetrics()); } @Override public void server(FusekiServer server) { - MetricsProviderRegistry.dataAccessPointMetrics(server.getDataAccessPointRegistry()); + MetricsProvider metricsProvider = MetricsProvider.getMetricsProvider(server.getServletContext()); + metricsProvider.dataAccessPointMetrics(metricsProvider, server.getDataAccessPointRegistry()); } } 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 e70a44d58d..ff0acf2fc4 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 @@ -34,7 +34,7 @@ import org.apache.jena.fuseki.FusekiConfigException; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.cmds.ServerArgs; import org.apache.jena.fuseki.main.sys.FusekiModule; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.rdf.model.Model; import org.apache.shiro.web.servlet.ShiroFilter; import org.eclipse.jetty.ee10.servlet.ServletContextHandler; @@ -45,8 +45,9 @@ import org.slf4j.LoggerFactory; /** * Fuseki Module for Apache Shiro. * <p> - * TODO - * Configuration + * Looks for an argument {@code --shiro=file}, and + * in environment variable {@code FUSEKI_SHIRO} + * (including via system proprties). */ public class FMod_Shiro implements FusekiModule { @@ -79,7 +80,6 @@ public class FMod_Shiro implements FusekiModule { private static ArgDecl argShiroIni = new ArgDecl(true, "shiro", "shiro-ini"); - // XXX Should be a per build variable. private String shiroFile = null; public FMod_Shiro() { @@ -122,7 +122,7 @@ public class FMod_Shiro implements FusekiModule { public void prepare(FusekiServer.Builder serverBuilder, Set<String> datasetNames, Model configModel) { if ( shiroFile == null ) { // Environment variable: FUSEKI_SHIRO - shiroFile = Lib.getenv(FusekiApp.envFusekiShiro); + shiroFile = Lib.getenv(FusekiServerCtl.envFusekiShiro); } if ( shiroFile == null ) { 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 a46ec343aa..51ad0fa32d 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 @@ -34,7 +34,7 @@ import org.apache.jena.fuseki.FusekiConfigException; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.cmds.ServerArgs; import org.apache.jena.fuseki.main.sys.FusekiModule; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.fuseki.validation.DataValidator; import org.apache.jena.fuseki.validation.IRIValidator; import org.apache.jena.fuseki.validation.QueryValidator; @@ -130,7 +130,7 @@ public class FMod_UI implements FusekiModule { // 2:: $FUSEKI_BASE/webapp // If the FUSEKI_BASE does not exists, it is created later in FMod_admin.prepare // and does not include Fuseki app. - String x = fromPath(FusekiApp.FUSEKI_BASE, directoryNameUI); + String x = fromPath(FusekiServerCtl.FUSEKI_BASE, directoryNameUI); if ( x != null ) { LOG.info("Fuseki UI - path resource: "+x); return x; diff --git a/jena-fuseki2/jena-fuseki-main/src/main/resources/org/apache/jena/fuseki/server/config.ttl b/jena-fuseki2/jena-fuseki-main/src/main/resources/org/apache/jena/fuseki/server/config.ttl index e69de29bb2..ef4f170a30 100644 --- a/jena-fuseki2/jena-fuseki-main/src/main/resources/org/apache/jena/fuseki/server/config.ttl +++ b/jena-fuseki2/jena-fuseki-main/src/main/resources/org/apache/jena/fuseki/server/config.ttl @@ -0,0 +1,2 @@ +## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0 +## Empty file \ No newline at end of file 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 6b4d86c8fb..8396f202fb 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 @@ -23,14 +23,12 @@ 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.main.prefixes.TS_PrefixesService; import org.apache.jena.fuseki.mod.TS_FusekiMods; @Suite @SelectClasses({ TS_FusekiMain.class, TS_SecurityFuseki.class, - TS_FusekiMods.class, - TS_PrefixesService.class + TS_FusekiMods.class }) public class TC_FusekiServer {} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java index f2ba8dda13..7371b5e674 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TS_FusekiMain.java @@ -21,7 +21,7 @@ package org.apache.jena.fuseki.main; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; -import org.apache.jena.fuseki.main.prefixes.TS_PrefixesService; +import org.apache.jena.fuseki.main.prefixes.PrefixesServiceTests; import org.apache.jena.fuseki.main.sys.TestFusekiModules; @Suite @@ -54,7 +54,7 @@ import org.apache.jena.fuseki.main.sys.TestFusekiModules; , TestPatchFuseki.class , TestFusekiCustomScriptFunc.class - , TS_PrefixesService.class + , PrefixesServiceTests.class , TestMetrics.class , TestFusekiShaclValidation.class 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 a0e8c17634..1711cb5d5a 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 @@ -50,7 +50,6 @@ public class TestConfigFile { """; - private static RDFConnection namedServices(String baseURL) { return RDFConnectionRemote.newBuilder() .destination(baseURL) diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestMetrics.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestMetrics.java index c473c18aaa..bc09f2a130 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestMetrics.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestMetrics.java @@ -18,6 +18,7 @@ package org.apache.jena.fuseki.main; import static org.apache.jena.http.HttpLib.handleResponseRtnString; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.InputStream; @@ -25,11 +26,13 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; +import org.junit.jupiter.api.Test; + import org.apache.jena.http.HttpEnv; import org.apache.jena.http.HttpLib; import org.apache.jena.riot.WebContent; import org.apache.jena.riot.web.HttpNames; -import org.junit.jupiter.api.Test; +import org.apache.jena.web.HttpSC; public class TestMetrics extends AbstractFusekiTest { @@ -38,8 +41,9 @@ public class TestMetrics extends AbstractFusekiTest { String r = serverURL() + "$/metrics"; HttpRequest request = HttpRequest.newBuilder().uri(HttpLib.toRequestURI(r)).build(); HttpResponse<InputStream> response = HttpLib.executeJDK(HttpEnv.getDftHttpClient(), request, BodyHandlers.ofInputStream()); - String body = handleResponseRtnString(response); + assertEquals(HttpSC.OK_200, response.statusCode()); + String body = handleResponseRtnString(response); String ct = response.headers().firstValue(HttpNames.hContentType).orElse(null); assertTrue(ct.contains(WebContent.contentTypeTextPlain)); assertTrue(ct.contains(WebContent.charsetUTF8)); diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/TS_PrefixesService.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/PrefixesServiceTests.java similarity index 96% rename from jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/TS_PrefixesService.java rename to jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/PrefixesServiceTests.java index 5ad83830a0..815847c62f 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/TS_PrefixesService.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/prefixes/PrefixesServiceTests.java @@ -28,6 +28,5 @@ import org.junit.platform.suite.api.Suite; , TestPrefixesServiceRDF.class , TestPrefixesServicePrefixesMap.class , TestPrefixesActionResponse.class - }) -public class TS_PrefixesService {} +public class PrefixesServiceTests {} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/LegacyModule.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/LegacyModule.java deleted file mode 100644 index d0c3404029..0000000000 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/LegacyModule.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.sys; - -/** testing the legacy-discovery code */ -public class LegacyModule implements FusekiModule { - - public LegacyModule() { - } - - @Override - public String name() { - return "LegacyModule"; - } - -} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleByServiceLoader.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleByServiceLoader.java index d7ccbfeff1..532ecc62aa 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleByServiceLoader.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleByServiceLoader.java @@ -26,6 +26,7 @@ import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.server.DataAccessPointRegistry; import org.apache.jena.rdf.model.Model; +// Must be in jena-fuseki-main/src/test/resources/META-INF/services/org.apache.jena.fuseki.main.sys.FusekiAutoModule public class ModuleByServiceLoader extends ModuleForTest implements FusekiAutoModule { private static ModuleByServiceLoader module = null; diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleForTest.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleForTest.java index a1b627911d..a87eaf45fa 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleForTest.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/ModuleForTest.java @@ -26,6 +26,7 @@ import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.server.DataAccessPointRegistry; import org.apache.jena.rdf.model.Model; +// Not autoloaded public class ModuleForTest implements FusekiModule { public AtomicInteger countPrepared = new AtomicInteger(0); diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/TestFusekiModules.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/TestFusekiModules.java index fda3ebbd6c..28c020e234 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/TestFusekiModules.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/sys/TestFusekiModules.java @@ -45,20 +45,13 @@ public class TestFusekiModules { // Created, not loaded } - private static void reset() { - ModuleByServiceLoader.reset(); - FusekiModules.resetSystemDefault(); - } - @Test public void lifecycle_1() { ModuleForTest module = new ModuleForTest(); FusekiModules fmods = FusekiModules.create(module); - // Mock default set. FusekiModules.setSystemDefault(fmods); - - FusekiServer.Builder builder = FusekiServer.create().port(0); try { + FusekiServer.Builder builder = FusekiServer.create().port(0); lifecycle(builder, module); } finally { FusekiModules.setSystemDefault(null); @@ -66,7 +59,8 @@ public class TestFusekiModules { } @Test public void lifecycle_2() { - reset(); + ModuleByServiceLoader.reset(); + FusekiModules.resetSystemDefault(); ModuleForTest module = new ModuleForTest(); FusekiModules fmods = FusekiModules.create(module); @@ -103,18 +97,24 @@ public class TestFusekiModules { } @Test public void autoload_1() { - // Included reload. + FusekiModules systemModules = FusekiModules.getSystemModules(); ModuleByServiceLoader.reset(); - FusekiModules.resetSystemDefault(); + try { + FusekiModules loadedModules = FusekiAutoModules.load(); + FusekiModules.setSystemDefault(loadedModules); - // Reloaded by FusekiModules.resetSystemDefault - assertEquals(1, ModuleByServiceLoader.countLoads.get()); - assertEquals(1, ModuleByServiceLoader.countStart.get()); + // Reloaded by FusekiModules.resetSystemDefault + assertEquals(1, ModuleByServiceLoader.countLoads.get(),"countLoads:"); + assertEquals(1, ModuleByServiceLoader.countStart.get(), "countStart:"); - // Default : loaded FusekiModules - FusekiServer.Builder builder = FusekiServer.create().port(0); - ModuleForTest module = ModuleByServiceLoader.lastLoaded(); - lifecycle(builder, module); + // Default : loaded FusekiModules + FusekiServer.Builder builder = FusekiServer.create().port(0); + ModuleForTest module = ModuleByServiceLoader.lastLoaded(); + lifecycle(builder, module); + } finally { + ModuleByServiceLoader.reset(); + FusekiModules.setSystemDefault(systemModules); + } } @Test public void server_module_1() { 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 6771fa2f90..f4f261e0e9 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 @@ -21,13 +21,18 @@ 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.TS_FusekiServerApp; +import org.apache.jena.fuseki.mod.admin.TestAdmin; +import org.apache.jena.fuseki.mod.admin.TestFusekiReload; +import org.apache.jena.fuseki.mod.admin.TestTemplateAddDataset; import org.apache.jena.fuseki.mod.metrics.TestModPrometheus; import org.apache.jena.fuseki.mod.shiro.TestModShiro; @Suite @SelectClasses({ - TS_FusekiServerApp.class, + // Admin + TestAdmin.class, + TestFusekiReload.class, + TestTemplateAddDataset.class, // UI // Prometheus 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/mod/TestFusekiServer.java index e0a6b2392d..c9d11ed691 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/mod/TestFusekiServer.java @@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; import org.apache.jena.fuseki.main.FusekiServer; -import org.apache.jena.fuseki.run.FusekiModServer; /** * Test for the whole Fuseki server, not components. diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TS_FusekiServerApp.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TS_FusekiServerApp.java deleted file mode 100644 index b36360b8cb..0000000000 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TS_FusekiServerApp.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.admin; - -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; - -@Suite -@SelectClasses({ - TestAdmin.class, - TestFusekiReload.class, - TestTemplateAddDataset.class, -}) -public class TS_FusekiServerApp { - -} diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestAdmin.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestAdmin.java index df0f6bafdd..396b14b289 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestAdmin.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestAdmin.java @@ -56,7 +56,7 @@ import org.apache.jena.fuseki.ctl.ActionSleep; import org.apache.jena.fuseki.ctl.JsonConstCtl; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.sys.FusekiModules; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.fuseki.mgt.ServerMgtConst; import org.apache.jena.fuseki.server.ServerConst; import org.apache.jena.fuseki.test.HttpTest; @@ -121,7 +121,7 @@ public class TestAdmin { server.stop(); serverURL = null; // Clearup FMod_Shiro. - System.getProperties().remove(FusekiApp.envFusekiShiro); + System.getProperties().remove(FusekiServerCtl.envFusekiShiro); } protected String urlRoot() { diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestTemplateAddDataset.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestTemplateAddDataset.java index 975876095d..9743802dcf 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestTemplateAddDataset.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/admin/TestTemplateAddDataset.java @@ -36,7 +36,7 @@ import org.apache.jena.atlas.web.TypedInputStream; import org.apache.jena.fuseki.Fuseki; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.sys.FusekiModules; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.http.HttpOp; import org.apache.jena.query.QueryExecution; import org.apache.jena.rdfconnection.RDFConnection; @@ -85,7 +85,7 @@ public class TestTemplateAddDataset { server.stop(); serverURL = null; // Clearup FMod_Shiro. - System.getProperties().remove(FusekiApp.envFusekiShiro); + System.getProperties().remove(FusekiServerCtl.envFusekiShiro); } protected String urlRoot() { @@ -143,7 +143,7 @@ public class TestTemplateAddDataset { int x1 = count(conn); assertEquals(1, x1); - Path pathDB = FusekiApp.dirDatabases.resolve(dbName); + Path pathDB = FusekiServerCtl.dirDatabases.resolve(dbName); if ( hasFiles ) assertTrue(Files.exists(pathDB)); diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/metrics/TestModPrometheus.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/metrics/TestModPrometheus.java index ce3be524fb..dbb475b002 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/metrics/TestModPrometheus.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/metrics/TestModPrometheus.java @@ -27,13 +27,13 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.sys.FusekiModules; +import org.apache.jena.fuseki.metrics.MetricsProvider; import org.apache.jena.fuseki.mod.prometheus.FMod_Prometheus; +import org.apache.jena.fuseki.mod.prometheus.PrometheusMetricsProvider; import org.apache.jena.http.HttpEnv; import org.apache.jena.http.HttpLib; import org.apache.jena.riot.WebContent; @@ -41,6 +41,7 @@ import org.apache.jena.riot.web.HttpNames; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.DatasetGraphFactory; +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class TestModPrometheus { private FusekiServer testServer = null; @@ -62,6 +63,15 @@ public class TestModPrometheus { } @Test + @Order(1) + public void metrics_available() { + MetricsProvider metricsProvider = MetricsProvider.getMetricsProvider(testServer.getServletContext()); + assertNotNull(metricsProvider); + assertTrue(metricsProvider instanceof PrometheusMetricsProvider); + } + + @Test + @Order(2) public void can_retrieve_metrics() { String metricsURL = testServer.serverURL()+"$/metrics"; HttpRequest request = HttpRequest.newBuilder().uri(HttpLib.toRequestURI(metricsURL)).build(); diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/shiro/TestModShiro.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/shiro/TestModShiro.java index dafc636f78..48f064f6a7 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/shiro/TestModShiro.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/mod/shiro/TestModShiro.java @@ -37,7 +37,7 @@ import org.apache.jena.fuseki.main.FusekiServer; import org.apache.jena.fuseki.main.cmds.FusekiMain; import org.apache.jena.fuseki.main.sys.FusekiModule; import org.apache.jena.fuseki.main.sys.FusekiModules; -import org.apache.jena.fuseki.mgt.FusekiApp; +import org.apache.jena.fuseki.mgt.FusekiServerCtl; import org.apache.jena.fuseki.system.FusekiLogging; import org.apache.jena.graph.Graph; import org.apache.jena.http.HttpEnv; @@ -62,7 +62,7 @@ public class TestModShiro { } @BeforeEach void before() { - System.getProperties().remove(FusekiApp.envFusekiShiro); + System.getProperties().remove(FusekiServerCtl.envFusekiShiro); AuthEnv.get().clearAuthEnv(); } @@ -71,7 +71,7 @@ public class TestModShiro { } @AfterAll static void afterAll() { - System.getProperties().remove(FusekiApp.envFusekiShiro); + System.getProperties().remove(FusekiServerCtl.envFusekiShiro); } private String unlocalhost(FusekiServer server, String dataset) { @@ -83,7 +83,7 @@ public class TestModShiro { /** Builder for a server with Shiro */ private FusekiServer.Builder serverBuilderWithShiro(String filename) { - System.getProperties().setProperty(FusekiApp.envFusekiShiro, filename); + System.getProperties().setProperty(FusekiServerCtl.envFusekiShiro, filename); FusekiModules modules = FusekiModules.create(FMod_Shiro.create()); return FusekiServer.create() .port(0) diff --git a/jena-fuseki2/jena-fuseki-main/src/test/resources/META-INF/services/org.apache.jena.fuseki.main.sys.FusekiModule b/jena-fuseki2/jena-fuseki-main/src/test/resources/META-INF/services/org.apache.jena.fuseki.main.sys.FusekiModule deleted file mode 100644 index fd5ce7ef2e..0000000000 --- a/jena-fuseki2/jena-fuseki-main/src/test/resources/META-INF/services/org.apache.jena.fuseki.main.sys.FusekiModule +++ /dev/null @@ -1 +0,0 @@ -org.apache.jena.fuseki.main.sys.LegacyModule diff --git a/jena-fuseki2/jena-fuseki-server/pom.xml b/jena-fuseki2/jena-fuseki-server/pom.xml index e38fec0b68..28cc33f10e 100644 --- a/jena-fuseki2/jena-fuseki-server/pom.xml +++ b/jena-fuseki2/jena-fuseki-server/pom.xml @@ -40,7 +40,13 @@ <dependency> <groupId>org.apache.jena</groupId> <artifactId>jena-fuseki-main</artifactId> - <version>${project.version}</version> + <version>5.3.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-fuseki-ui</artifactId> + <version>5.3.0-SNAPSHOT</version> </dependency> <dependency> @@ -99,7 +105,7 @@ <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <mainClass>org.apache.jena.fuseki.main.cmds.FusekiMainCmd</mainClass> + <mainClass>org.apache.jena.fuseki.main.cmds.FusekiServerCmd</mainClass> <!-- https://issues.apache.org/jira/browse/LOG4J2-2537 --> <manifestEntries> <Multi-Release>true</Multi-Release> diff --git a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerListener.java b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerListener.java index 469e396f32..50357959a4 100644 --- a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerListener.java +++ b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiServerListener.java @@ -21,11 +21,11 @@ package org.apache.jena.fuseki.webapp; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletContextEvent; import jakarta.servlet.ServletContextListener; - import org.apache.jena.fuseki.Fuseki; import org.apache.jena.fuseki.FusekiException; import org.apache.jena.fuseki.cmd.FusekiArgs; -import org.apache.jena.fuseki.metrics.MetricsProviderRegistry; +import org.apache.jena.fuseki.metrics.MetricsProvider; +import org.apache.jena.fuseki.metrics.PrometheusMetricsProvider; import org.apache.jena.fuseki.server.DataAccessPointRegistry; import org.apache.jena.fuseki.server.FusekiCoreInfo; import org.apache.jena.fuseki.server.OperationRegistry; @@ -102,7 +102,9 @@ public class FusekiServerListener implements ServletContextListener { //Fuseki.configLog.info("Register: "+dap.getName()); }); - MetricsProviderRegistry.dataAccessPointMetrics(dataAccessPointRegistry); + MetricsProvider metricsProvider = new PrometheusMetricsProvider(); + MetricsProvider.setMetricsProvider(servletContext, metricsProvider); + metricsProvider.dataAccessPointMetrics(metricsProvider, dataAccessPointRegistry); } catch (Throwable th) { Fuseki.serverLog.error("Exception in initialization: {}", th.getMessage());
