/* * 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 ; import java.util.Calendar ; import java.util.TimeZone ; import java.util.concurrent.TimeUnit ; import org.apache.jena.atlas.lib.DateTimeUtils ; import org.apache.jena.query.ARQ ; import org.apache.jena.riot.system.stream.LocatorFTP ; import org.apache.jena.riot.system.stream.LocatorHTTP ; import org.apache.jena.riot.system.stream.StreamManager ; import org.apache.jena.sparql.SystemARQ ; import org.apache.jena.sparql.lib.Metadata ; import org.apache.jena.sparql.mgt.SystemInfo ; import org.apache.jena.sparql.util.Context ; import org.apache.jena.sparql.util.MappingRegistry ; import org.apache.jena.system.JenaSystem ; import org.apache.jena.tdb.TDB ; import org.apache.jena.tdb.transaction.TransactionManager ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; public class Fuseki { // General fixed constants. // See also FusekiServer for the naming on the filesystem /** Path as package name */ static public String PATH = "org.apache.jena.fuseki" ; /** a unique IRI for the Fuseki namespace */ static public String FusekiIRI = "http://jena.apache.org/Fuseki" ; /** * a unique IRI including the symbol notation for which properties should be * appended */ static public String FusekiSymbolIRI = "http://jena.apache.org/fuseki#" ; /** Default location of the pages for the Fuseki UI */ static public String PagesStatic = "pages" ; /** Dummy base URi string for parsing SPARQL Query and Update requests */ static public final String BaseParserSPARQL = "http://server/unset-base/" ; /** Dummy base URi string for parsing SPARQL Query and Update requests */ static public final String BaseUpload = "http://server/unset-base/" ; /** * A relative resources path to the location of * <code>fuseki-properties.xml</code> file. */ static private String metadataLocation = "org/apache/jena/fuseki/fuseki-properties.xml" ; /** * Object which holds metadata specified within * {@link Fuseki#metadataLocation} */ static private Metadata metadata = initMetadata() ; private static Metadata initMetadata() { Metadata m = new Metadata() ; // m.addMetadata(metadataDevLocation) ; m.addMetadata(metadataLocation) ; return m ; } /** The name of the Fuseki server. Set to the string <code>Fuseki</code> by default. */ static public final String NAME = "Fuseki" ; /** Version of this Fuseki instance */ static public final String VERSION = metadata.get(PATH + ".version", "development") ; /** Date when Fuseki was built */ static public final String BUILD_DATE = metadata.get(PATH + ".build.datetime", "unknown") ; /** Supporting Graph Store Protocol direct naming. * <p> * A GSP "direct name" is a request, not using ?default or ?graph=, that names the graph * by the request URL so it is of the form {@code http://server/dataset/graphname...}. * There are two cases: looking like a service {@code http://server/dataset/service} and * a longer URL that can't be a service {@code http://server/dataset/segment/segment/...}. * <p> * GSP "direct name" is usually off. It is a rare feature and because of hard wiring to the URL * quite sensitive to request route. * <p> * The following places use this switch: * <li>{@code FusekiFilter} for the "clearly not a service" case * <li>{@code SPARQL_UberServlet}, end of dispatch (after checking for http://server/dataset/service) * <li>{@code SPARQL_GSP.determineTarget} This is all-purpose code - should not get there because of other checks. * */ static public final boolean GSP_DIRECT_NAMING = false ; /** Are we in development mode? That means a SNAPSHOT, or no VERSION * because maven has not filtered the fuseki-properties.xml file. */ public static boolean developmentMode ; static { // See ServletBase.setCommonheaders // If it look like a SNAPSHOT, or it's not set, we are in development mode. developmentMode = ( VERSION == null || VERSION.equals("development") || VERSION.contains("SNAPSHOT") ) ; } public static boolean outputJettyServerHeader = developmentMode ; public static boolean outputFusekiServerHeader = developmentMode ; /** An identifier for the HTTP Fuseki server instance */ static public final String serverHttpName = NAME + " (" + VERSION + ")" ; /** Logger name for operations */ public static final String actionLogName = PATH + ".Fuseki" ; /** Instance of log for operations */ public static final Logger actionLog = LoggerFactory.getLogger(actionLogName) ; /** Logger name for standard webserver log file request log */ public static final String requestLogName = PATH + ".Request" ; // See HttpAction.finishRequest. // Normally OFF /** Instance of a log for requests: format is NCSA. */ public static final Logger requestLog = LoggerFactory.getLogger(requestLogName) ; /** Admin log file for operations. */ public static final String adminLogName = PATH + ".Admin" ; /** Instance of log for operations. */ public static final Logger adminLog = LoggerFactory.getLogger(adminLogName) ; /** Admin log file for operations. */ public static final String builderLogName = PATH + ".Builder" ; /** Instance of log for operations. */ public static final Logger builderLog = LoggerFactory.getLogger(builderLogName) ; /** Validation log file for operations. */ public static final String validationLogName = PATH + ".Validate" ; /** Instance of log for validation. */ public static final Logger validationLog = LoggerFactory.getLogger(adminLogName) ; /** Actual log file for general server messages. */ public static final String serverLogName = PATH + ".Server" ; /** Instance of log for general server messages. */ public static final Logger serverLog = LoggerFactory.getLogger(serverLogName) ; /** Logger used for the servletContent.log operations (if settable -- depends on environment) */ public static final String servletRequestLogName = PATH + ".Servlet" ; /** Actual log file for config server messages. */ public static final String configLogName = PATH + ".Config" ; /** Instance of log for config server messages. */ public static final Logger configLog = LoggerFactory.getLogger(configLogName) ; /** Instance of log for config server message s */ public static boolean verboseLogging = false ; /** * An instance of management for stream opening, including redirecting * through a location mapper whereby a name (e.g. URL) is redirected to * another name (e.g. local file). * */ public static final StreamManager webStreamManager ; static { webStreamManager = new StreamManager() ; // Only know how to handle http URLs webStreamManager.addLocator(new LocatorHTTP()) ; webStreamManager.addLocator(new LocatorFTP()) ; } /** Default (and development) root of the Fuseki installation for fixed files. */ public static String DFT_FUSEKI_HOME = "." ; /** Default (and development) root of the varying files in this deployment. */ public static String DFT_FUSEKI_BASE = "." ; private static boolean initialized = false ; // Server start time and uptime. private static final long startMillis = System.currentTimeMillis() ; // Hide server locale private static final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("00:00")) ; static { cal.setTimeInMillis(startMillis) ; } // Exactly the same start point! private static final String startDateTime = DateTimeUtils.calendarToXSDDateTimeString(cal) ; /** Return the number of milliseconds since the server started */ public static long serverUptimeMillis() { return System.currentTimeMillis() - startMillis ; } /** Server uptime in seconds */ public static long serverUptimeSeconds() { long x = System.currentTimeMillis() - startMillis ; return TimeUnit.MILLISECONDS.toSeconds(x) ; } /** XSD DateTime for when the server started */ public static String serverStartedAt() { return startDateTime ; } /** * Initialize an instance of the Fuseki server stack. * This is not done via Jena's initialization mechanism * but done explicitly to give more control. * Touching this class causes this to happen * (see static block at the end of this class). */ public synchronized static void init() { if ( initialized ) return ; initialized = true ; JenaSystem.init() ; SystemInfo sysInfo = new SystemInfo(FusekiIRI, PATH, VERSION, BUILD_DATE) ; SystemARQ.registerSubSystem(sysInfo) ; MappingRegistry.addPrefixMapping("fuseki", FusekiSymbolIRI) ; TDB.setOptimizerWarningFlag(false) ; // Don't set TDB batch commits. // This can be slower, but it less memory hungry and more predictable. TransactionManager.QueueBatchSize = 0 ; } /** * Get server global {@link org.apache.jena.sparql.util.Context}. * * @return {@link org.apache.jena.query.ARQ#getContext()} */ public static Context getContext() { return ARQ.getContext() ; } // Force a call to init. static { init() ; } }