org.apache.jena.fuseki.FusekiCmd Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-fuseki1 Show documentation
Show all versions of jena-fuseki1 Show documentation
Fuseki is a SPARQL 1.1 Server
/*
* 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 static org.apache.jena.fuseki.Fuseki.serverLog ;
import java.io.File ;
import java.io.InputStream ;
import java.util.List ;
import java.util.Objects;
import arq.cmdline.CmdARQ ;
import arq.cmdline.ModDatasetAssembler ;
import jena.cmd.ArgDecl ;
import jena.cmd.CmdException ;
import org.apache.jena.atlas.io.IO ;
import org.apache.jena.atlas.lib.FileOps ;
import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.atlas.logging.LogCtl ;
import org.apache.jena.fuseki.mgt.ManagementServer ;
import org.apache.jena.fuseki.server.FusekiConfig ;
import org.apache.jena.fuseki.server.SPARQLServer ;
import org.apache.jena.fuseki.server.ServerConfig ;
import org.apache.jena.query.ARQ ;
import org.apache.jena.query.Dataset ;
import org.apache.jena.riot.Lang ;
import org.apache.jena.riot.RDFDataMgr ;
import org.apache.jena.riot.RDFLanguages ;
import org.apache.jena.riot.SysRIOT ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.core.DatasetGraphFactory ;
import org.apache.jena.tdb.TDB ;
import org.apache.jena.tdb.TDBFactory ;
import org.apache.jena.tdb.sys.Names ;
import org.apache.jena.tdb.transaction.TransactionManager ;
import org.eclipse.jetty.server.Server ;
import org.slf4j.Logger ;
public class FusekiCmd extends CmdARQ
{
private static String log4Jsetup = StrUtils.strjoinNL(
"## Plain output to stdout"
, "log4j.appender.jena.plain=org.apache.log4j.ConsoleAppender"
, "log4j.appender.jena.plain.target=System.out"
, "log4j.appender.jena.plain.layout=org.apache.log4j.PatternLayout"
, "log4j.appender.jena.plain.layout.ConversionPattern=%d{HH:mm:ss} %-5p %m%n"
, "## Plain output with level, to stderr"
, "log4j.appender.jena.plainlevel=org.apache.log4j.ConsoleAppender"
, "log4j.appender.jena.plainlevel.target=System.err"
, "log4j.appender.jena.plainlevel.layout=org.apache.log4j.PatternLayout"
, "log4j.appender.jena.plainlevel.layout.ConversionPattern=%d{HH:mm:ss} %-5p %m%n"
, "## Everything"
, "log4j.rootLogger=INFO, jena.plain"
, "log4j.logger.org.apache.jena=WARN"
, "# Server log."
, "log4j.logger.org.apache.jena.fuseki.Server=INFO"
, "# Request log."
, "log4j.logger.org.apache.jena.fuseki.Fuseki=INFO"
, "log4j.logger.org.apache.jena.tdb.loader=INFO"
, "log4j.logger.org.eclipse.jetty=ERROR"
, "## Parser output"
, "log4j.additivity."+SysRIOT.riotLoggerName+"=false"
, "log4j.logger."+SysRIOT.riotLoggerName+"=INFO, jena.plainlevel "
) ;
// Set logging.
// 1/ Use log4j.configuration is defined.
// 2/ Use file:log4j.properties
// 3/ Use Built in.
static void setLogging() {
// No loggers have been created but configuration may have been set up.
String x = System.getProperty("log4j.configuration", null) ;
if ( x != null && ! x.equals("set") ) {
// "set" indicates that CmdMain set logging.
// Use standard log4j initialization.
return ;
}
String fn = "log4j.properties" ;
File f = new File(fn) ;
if ( f.exists() ) {
// Use file log4j.properties
System.setProperty("log4j.configuration", "file:"+fn) ;
return ;
}
// Use built-in for Fuseki.
LogCtl.resetLogging(log4Jsetup) ;
}
static { setLogging() ; }
// Arguments:
// --update
// Specific switches:
// --admin=on/off
// --http-update
// --http-get
// --sparql-query
// --sparql-update
// pages/validators/
// pages/control/
// pages/query/ or /pages/sparql/
private static ArgDecl argMgtPort = new ArgDecl(ArgDecl.HasValue, "mgtPort", "mgtport") ;
private static ArgDecl argMem = new ArgDecl(ArgDecl.NoValue, "mem") ;
private static ArgDecl argAllowUpdate = new ArgDecl(ArgDecl.NoValue, "update", "allowUpdate") ;
private static ArgDecl argFile = new ArgDecl(ArgDecl.HasValue, "file") ;
private static ArgDecl argMemTDB = new ArgDecl(ArgDecl.NoValue, "memtdb", "memTDB") ;
private static ArgDecl argTDB = new ArgDecl(ArgDecl.HasValue, "loc", "location") ;
private static ArgDecl argPort = new ArgDecl(ArgDecl.HasValue, "port") ;
private static ArgDecl argLocalhost = new ArgDecl(ArgDecl.NoValue, "localhost", "local") ;
private static ArgDecl argTimeout = new ArgDecl(ArgDecl.HasValue, "timeout") ;
private static ArgDecl argFusekiConfig = new ArgDecl(ArgDecl.HasValue, "config", "conf") ;
private static ArgDecl argJettyConfig = new ArgDecl(ArgDecl.HasValue, "jetty-config") ;
private static ArgDecl argGZip = new ArgDecl(ArgDecl.HasValue, "gzip") ;
private static ArgDecl argUber = new ArgDecl(ArgDecl.NoValue, "uber", "über") ; // Use the überservlet (experimental)
private static ArgDecl argBasicAuth = new ArgDecl(ArgDecl.HasValue, "basic-auth") ;
private static ArgDecl argGSP = new ArgDecl(ArgDecl.NoValue, "gsp") ; // GSP compliance mode
private static ArgDecl argHome = new ArgDecl(ArgDecl.HasValue, "home") ;
private static ArgDecl argPages = new ArgDecl(ArgDecl.HasValue, "pages") ;
//private static ModLocation modLocation = new ModLocation() ;
private static ModDatasetAssembler modDataset = new ModDatasetAssembler() ;
// fuseki [--mem|--desc assembler.ttl] [--port PORT] **** /datasetURI
static public void main(String...argv)
{
// Just to make sure ...s
Fuseki.init() ;
new FusekiCmd(argv).mainRun() ;
}
private int port = 3030 ;
private int mgtPort = -1 ;
private boolean listenLocal = false ;
private DatasetGraph dsg = null ;
private String datasetPath = null ;
private boolean allowUpdate = false ;
private String fusekiConfigFile = null ;
private boolean enableCompression = true ;
private String jettyConfigFile = null ;
private String authConfigFile = null ;
private String homeDir = null ;
private String pagesDir = null ;
public FusekiCmd(String...argv)
{
super(argv) ;
if ( false )
// Consider ...
TransactionManager.QueueBatchSize = TransactionManager.QueueBatchSize / 2 ;
getUsage().startCategory("Fuseki") ;
addModule(modDataset) ;
add(argMem, "--mem", "Create an in-memory, non-persistent dataset for the server") ;
add(argFile, "--file=FILE", "Create an in-memory, non-persistent dataset for the server, initialised with the contents of the file") ;
add(argTDB, "--loc=DIR", "Use an existing TDB database (or create if does not exist)") ;
add(argMemTDB, "--memTDB", "Create an in-memory, non-persistent dataset using TDB (testing only)") ;
add(argPort, "--port", "Listen on this port number") ;
add(argPages, "--pages=DIR", "Set of pages to serve as static content") ;
// Set via jetty config file.
add(argLocalhost, "--localhost", "Listen only on the localhost interface") ;
add(argTimeout, "--timeout=", "Global timeout applied to queries (value in ms) -- format is X[,Y] ") ;
add(argAllowUpdate, "--update", "Allow updates (via SPARQL Update and SPARQL HTTP Update)") ;
add(argFusekiConfig, "--config=", "Use a configuration file to determine the services") ;
add(argJettyConfig, "--jetty-config=FILE", "Set up the server (not services) with a Jetty XML file") ;
add(argBasicAuth, "--basic-auth=FILE", "Configure basic auth using provided Jetty realm file, ignored if --jetty-config is used") ;
add(argMgtPort, "--mgtPort=port", "Enable the management commands on the given port") ;
add(argHome, "--home=DIR", "Root of Fuseki installation (overrides environment variable FUSEKI_HOME)") ;
add(argGZip, "--gzip=on|off", "Enable GZip compression (HTTP Accept-Encoding) if request header set") ;
add(argUber) ;
//add(argGSP) ;
super.modVersion.addClass(TDB.class) ;
super.modVersion.addClass(Fuseki.class) ;
}
static String argUsage = "[--config=FILE] [--mem|--desc=AssemblerFile|--file=FILE] [--port PORT] /DatasetPathName" ;
@Override
protected String getSummary()
{
return getCommandName()+" "+argUsage ;
}
@Override
protected void processModulesAndArgs()
{
int x = 0 ;
Logger log = Fuseki.serverLog ;
if ( contains(argFusekiConfig) )
fusekiConfigFile = getValue(argFusekiConfig) ;
ArgDecl assemblerDescDecl = new ArgDecl(ArgDecl.HasValue, "desc", "dataset") ;
if ( contains(argMem) ) x++ ;
if ( contains(argFile) ) x++ ;
if ( contains(assemblerDescDecl) ) x++ ;
if ( contains(argTDB) ) x++ ;
if ( contains(argMemTDB) ) x++ ;
if ( fusekiConfigFile != null )
{
if ( x >= 1 )
throw new CmdException("Dataset specified on the command line but a configuration file also given.") ;
}
else
{
if ( x != 1 )
throw new CmdException("Required: either --config=FILE or one of --mem, --file, --loc or --desc") ;
}
// One of:
// argMem, argFile, argMemTDB, argTDB,
if ( contains(argMem) )
{
log.info("Dataset: in-memory") ;
dsg = DatasetGraphFactory.create() ;
}
if ( contains(argFile) )
{
dsg = DatasetGraphFactory.create() ;
// replace by RiotLoader after ARQ refresh.
String filename = getValue(argFile) ;
log.info("Dataset: in-memory: load file: "+filename) ;
if ( ! FileOps.exists(filename) )
throw new CmdException("File not found: "+filename) ;
Lang language = RDFLanguages.filenameToLang(filename) ;
if ( language == null )
throw new CmdException("Can't guess language for file: "+filename) ;
InputStream input = IO.openFile(filename) ;
if ( RDFLanguages.isQuads(language) )
RDFDataMgr.read(dsg, filename) ;
else
RDFDataMgr.read(dsg.getDefaultGraph(), filename) ;
}
if ( contains(argMemTDB) )
{
log.info("TDB dataset: in-memory") ;
dsg = TDBFactory.createDatasetGraph() ;
}
if ( contains(argTDB) )
{
String dir = getValue(argTDB) ;
if ( Objects.equals(dir, Names.memName) ) {
log.info("TDB dataset: in-memory") ;
} else {
if ( ! FileOps.exists(dir) )
throw new CmdException("Directory not found: "+dir) ;
log.info("TDB dataset: directory="+dir) ;
}
dsg = TDBFactory.createDatasetGraph(dir) ;
}
// Otherwise
if ( contains(assemblerDescDecl) )
{
log.info("Dataset from assembler") ;
Dataset ds = modDataset.createDataset() ;
if ( ds != null )
dsg = ds.asDatasetGraph() ;
}
if ( contains(argFusekiConfig) )
{
if ( dsg != null )
throw new CmdException("(internal error) Dataset specificed on the command line but a a configuration file also given.") ;
fusekiConfigFile = getValue(argFusekiConfig) ;
}
if ( contains(argPort) )
{
String portStr = getValue(argPort) ;
try {
port = Integer.parseInt(portStr) ;
} catch (NumberFormatException ex)
{
throw new CmdException(argPort.getKeyName()+" : bad port number: "+portStr) ;
}
}
if ( contains(argMgtPort) )
{
String mgtPortStr = getValue(argMgtPort) ;
try {
mgtPort = Integer.parseInt(mgtPortStr) ;
} catch (NumberFormatException ex)
{
throw new CmdException(argMgtPort.getKeyName()+" : bad port number: "+mgtPortStr) ;
}
}
if ( contains(argLocalhost) )
listenLocal = true ;
if ( fusekiConfigFile == null && dsg == null )
throw new CmdException("No dataset defined and no configuration file: "+argUsage) ;
if ( dsg != null )
{
if ( getPositional().size() == 0 )
throw new CmdException("No dataset path name given") ;
if ( getPositional().size() > 1 )
throw new CmdException("Multiple dataset path names given") ;
datasetPath = getPositionalArg(0) ;
if ( datasetPath.length() > 0 && ! datasetPath.startsWith("/") )
throw new CmdException("Dataset path name must begin with a /: "+datasetPath) ;
allowUpdate = contains(argAllowUpdate) ;
}
if ( contains(argTimeout) )
{
String str = getValue(argTimeout) ;
ARQ.getContext().set(ARQ.queryTimeout, str) ;
}
if ( contains(argJettyConfig) )
{
jettyConfigFile = getValue(argJettyConfig) ;
if ( !FileOps.exists(jettyConfigFile) )
throw new CmdException("No such file: "+jettyConfigFile) ;
}
if ( contains(argBasicAuth) )
{
authConfigFile = getValue(argBasicAuth) ;
if ( !FileOps.exists(authConfigFile) )
throw new CmdException("No such file: " + authConfigFile) ;
}
if ( contains(argHome) )
{
List args = super.getValues(argHome) ;
homeDir = args.get(args.size()-1) ;
}
if ( contains(argPages) )
{
List args = super.getValues(argPages) ;
pagesDir = args.get(args.size()-1) ;
}
if ( contains(argGZip) )
{
if ( ! hasValueOfTrue(argGZip) && ! hasValueOfFalse(argGZip) )
throw new CmdException(argGZip.getNames().get(0)+": Not understood: "+getValue(argGZip)) ;
enableCompression = super.hasValueOfTrue(argGZip) ;
}
if ( contains(argUber) )
SPARQLServer.überServlet = true ;
if ( contains(argGSP) )
{
SPARQLServer.überServlet = true ;
Fuseki.graphStoreProtocolPostCreate = true ;
}
}
private static String sort_out_dir(String path)
{
path.replace('\\', '/') ;
if ( ! path.endsWith("/"))
path = path +"/" ;
return path ;
}
@Override
protected void exec()
{
if ( homeDir == null )
{
if ( System.getenv(Fuseki.FusekiHomeEnv) != null )
homeDir = System.getenv(Fuseki.FusekiHomeEnv) ;
else
homeDir = "." ;
}
homeDir = sort_out_dir(homeDir) ;
Fuseki.configLog.info("Home Directory: " + FileOps.fullDirectoryPath(homeDir));
if ( ! FileOps.exists(homeDir) )
Fuseki.configLog.warn("No such directory for Fuseki home: "+homeDir) ;
String staticContentDir = pagesDir ;
if ( staticContentDir == null )
staticContentDir = homeDir+Fuseki.PagesStatic ;
Fuseki.configLog.debug("Static Content Directory: "+ FileOps.fullDirectoryPath(staticContentDir)) ;
if ( ! FileOps.exists(staticContentDir) ) {
Fuseki.configLog.warn("No such directory for static content: " + FileOps.fullDirectoryPath(staticContentDir)) ;
Fuseki.configLog.warn("You may need to set the --pages or --home option to configure static content correctly");
}
if ( jettyConfigFile != null )
Fuseki.configLog.info("Jetty configuration: "+jettyConfigFile) ;
ServerConfig serverConfig ;
if ( fusekiConfigFile != null )
{
Fuseki.configLog.info("Configuration file: "+fusekiConfigFile) ;
serverConfig = FusekiConfig.configure(fusekiConfigFile) ;
}
else
{
serverConfig = FusekiConfig.defaultConfiguration(datasetPath, dsg, allowUpdate, listenLocal) ;
if ( ! allowUpdate )
Fuseki.serverLog.info("Running in read-only mode.");
}
// TODO Get from parsing config file.
serverConfig.port = port ;
serverConfig.pages = staticContentDir ;
serverConfig.mgtPort = mgtPort ;
serverConfig.pagesPort = port ;
serverConfig.loopback = listenLocal ;
serverConfig.enableCompression = enableCompression ;
serverConfig.jettyConfigFile = jettyConfigFile ;
serverConfig.authConfigFile = authConfigFile ;
serverConfig.verboseLogging = ( super.isVerbose() || super.isDebug() ) ;
SPARQLServer server = new SPARQLServer(serverConfig) ;
// Temporary
Fuseki.setServer(server) ;
Server mgtServer = null ;
if ( mgtPort > 0 )
{
Fuseki.configLog.info("Management services on port "+mgtPort) ;
mgtServer = ManagementServer.createManagementServer(mgtPort) ;
try { mgtServer.start() ; }
catch (java.net.BindException ex)
{ serverLog.error("SPARQLServer: Failed to start management server: " + ex.getMessage()) ; System.exit(1) ; }
catch (Exception ex)
{ serverLog.error("SPARQLServer: Failed to start management server: " + ex.getMessage(), ex) ; System.exit(1) ; }
}
try {
server.start() ;
} catch (FusekiException ex) {
serverLog.warn("Failed to start the server.", ex) ;
}
try { server.getServer().join() ; } catch (Exception ex) {}
if ( mgtServer != null )
{
try { mgtServer.stop() ; }
catch (Exception e) { serverLog.warn("Failed to cleanly stop the management server", e) ; }
}
System.exit(0) ;
}
@Override
protected String getCommandName()
{
return "fuseki" ;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy