You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2017/07/07 15:30:51 UTC

[1/3] jena git commit: JENA-1371: Rename FusekiServer (in Fuseki-full) as FusekiSystem.

Repository: jena
Updated Branches:
  refs/heads/master 6857bf5b8 -> f30ac0f89


JENA-1371: Rename FusekiServer (in Fuseki-full) as FusekiSystem.


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/1e6afdd4
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/1e6afdd4
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/1e6afdd4

Branch: refs/heads/master
Commit: 1e6afdd4f600809103e30bc3268b7931a7bf82bd
Parents: 6857bf5
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Jul 7 11:46:23 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Jul 7 11:46:54 2017 +0100

----------------------------------------------------------------------
 .../apache/jena/fuseki/build/FusekiConfig.java  |   6 +-
 .../org/apache/jena/fuseki/cmd/FusekiCmd.java   |   4 +-
 .../jena/fuseki/mgt/ActionBackupList.java       |   8 +-
 .../apache/jena/fuseki/mgt/ActionDatasets.java  |  12 +-
 .../java/org/apache/jena/fuseki/mgt/Backup.java |   4 +-
 .../apache/jena/fuseki/server/FusekiEnv.java    |  55 +--
 .../apache/jena/fuseki/server/FusekiServer.java | 420 -----------------
 .../fuseki/server/FusekiServerListener.java     |  10 +-
 .../apache/jena/fuseki/server/FusekiSystem.java | 463 +++++++++++++++++++
 .../fuseki/server/ShiroEnvironmentLoader.java   |   2 +-
 .../apache/jena/fuseki/server/SystemState.java  |   2 +-
 .../java/org/apache/jena/fuseki/ServerCtl.java  |   2 +-
 12 files changed, 490 insertions(+), 498 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
----------------------------------------------------------------------
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 b422383..5213f01 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
@@ -108,7 +108,7 @@ public class FusekiConfig {
     
     private static List<DataAccessPoint> servicesAndDatasets(Model model) {
         // Old style configuration file : server to services.
-        DatasetDescriptionRegistry dsDescMap = FusekiServer.registryForBuild() ;
+        DatasetDescriptionRegistry dsDescMap = FusekiSystem.registryForBuild() ;
         // ---- Services
         ResultSet rs = FusekiLib.query("SELECT * { ?s fu:services [ list:member ?service ] }", model) ;
         List<DataAccessPoint> accessPoints = new ArrayList<>() ;
@@ -177,7 +177,7 @@ public class FusekiConfig {
         List<DataAccessPoint> dataServiceRef = new ArrayList<>() ;
         try (DirectoryStream<Path> stream = Files.newDirectoryStream(pDir, filter)) {
             for ( Path p : stream ) {
-                DatasetDescriptionRegistry dsDescMap = FusekiServer.registryForBuild() ;
+                DatasetDescriptionRegistry dsDescMap = FusekiSystem.registryForBuild() ;
                 String fn = IRILib.filenameToIRI(p.toString()) ;
                 log.info("Load configuration: "+fn);
                 Model m = readAssemblerFile(fn) ;
@@ -219,7 +219,7 @@ public class FusekiConfig {
     // ---- System database
     /** Read the system database */
     public static List<DataAccessPoint> readSystemDatabase(Dataset ds) {
-        DatasetDescriptionRegistry dsDescMap = FusekiServer.registryForBuild() ;
+        DatasetDescriptionRegistry dsDescMap = FusekiSystem.registryForBuild() ;
         String qs = StrUtils.strjoinNL
             (SystemState.PREFIXES ,
              "SELECT * {" ,

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
index 7277d50..28c0dbd 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/cmd/FusekiCmd.java
@@ -34,7 +34,7 @@ import org.apache.jena.fuseki.build.Template ;
 import org.apache.jena.fuseki.jetty.JettyFuseki ;
 import org.apache.jena.fuseki.jetty.JettyServerConfig ;
 import org.apache.jena.fuseki.server.FusekiEnv ;
-import org.apache.jena.fuseki.server.FusekiServer ;
+import org.apache.jena.fuseki.server.FusekiSystem ;
 import org.apache.jena.fuseki.server.FusekiServerListener ;
 import org.apache.jena.fuseki.server.FusekiInitialConfig ;
 import org.apache.jena.query.ARQ ;
@@ -220,7 +220,7 @@ public class FusekiCmd {
             if ( ! cmdlineConfigPresent && cmdLineConfig.fusekiCmdLineConfigFile == null ) {
                 // Turn command line argument into an absolute file name.
                 FusekiEnv.setEnvironment();
-                Path cfg = FusekiEnv.FUSEKI_BASE.resolve(FusekiServer.DFT_CONFIG).toAbsolutePath() ;
+                Path cfg = FusekiEnv.FUSEKI_BASE.resolve(FusekiSystem.DFT_CONFIG).toAbsolutePath() ;
                 if ( Files.exists(cfg) )
                     cmdLineConfig.fusekiServerConfigFile = cfg.toString() ;
             }

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
index 1e6cb6e..498060d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackupList.java
@@ -34,7 +34,7 @@ import javax.servlet.http.HttpServletResponse ;
 
 import org.apache.jena.atlas.json.JsonBuilder ;
 import org.apache.jena.atlas.json.JsonValue ;
-import org.apache.jena.fuseki.server.FusekiServer ;
+import org.apache.jena.fuseki.server.FusekiSystem ;
 import org.apache.jena.fuseki.servlets.HttpAction ;
 import org.apache.jena.fuseki.servlets.ServletOps ;
 
@@ -68,11 +68,11 @@ public class ActionBackupList extends ActionCtl {
     } ;
 
     private JsonValue description(HttpAction action) {
-        if ( ! Files.isDirectory(FusekiServer.dirBackups) )
-            ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiServer.dirBackups)) ;
+        if ( ! Files.isDirectory(FusekiSystem.dirBackups) )
+            ServletOps.errorOccurred(format("[%d] Backup area '%s' is not a directory", action.id, FusekiSystem.dirBackups)) ;
         
         List<Path> paths = new ArrayList<>() ;
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiServer.dirBackups, filterVisibleFiles)) {
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiSystem.dirBackups, filterVisibleFiles)) {
             stream.forEach(paths::add) ;
         } catch (IOException ex) {
             action.log.error(format("[%d] Backup file list :: IOException :: %s", action.id, ex.getMessage())) ;

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
index 8f8bfae..c98fb42 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -110,7 +110,7 @@ public class ActionDatasets extends ActionContainerItem {
     @Override
     protected JsonValue execPostContainer(HttpAction action) {
         JenaUUID uuid = JenaUUID.generate() ;
-        DatasetDescriptionRegistry registry = FusekiServer.registryForBuild() ;
+        DatasetDescriptionRegistry registry = FusekiSystem.registryForBuild() ;
         
         ContentType ct = FusekiLib.getContentType(action) ;
         
@@ -143,7 +143,7 @@ public class ActionDatasets extends ActionContainerItem {
             // ----
             // Keep a persistent copy immediately.  This is not used for
             // anything other than being "for the record".
-            systemFileCopy = FusekiServer.dirFileArea.resolve(uuid.asString()).toString() ;
+            systemFileCopy = FusekiSystem.dirFileArea.resolve(uuid.asString()).toString() ;
             try ( OutputStream outCopy = IO.openOutputFile(systemFileCopy) ) {
                 RDFDataMgr.write(outCopy, model, Lang.TURTLE) ;
             }
@@ -191,8 +191,8 @@ public class ActionDatasets extends ActionContainerItem {
                 // And abort.
                 ServletOps.error(HttpSC.CONFLICT_409, "Name already registered "+datasetPath) ;
             
-            configFile = FusekiEnv.generateConfigurationFilename(datasetPath) ;
-            List<String> existing = FusekiEnv.existingConfigurationFile(datasetPath) ;
+            configFile = FusekiSystem.generateConfigurationFilename(datasetPath) ;
+            List<String> existing = FusekiSystem.existingConfigurationFile(datasetPath) ;
             if ( ! existing.isEmpty() )
                 ServletOps.error(HttpSC.CONFLICT_409, "Configuration file for '"+datasetPath+"' already exists") ;
 
@@ -289,7 +289,7 @@ public class ActionDatasets extends ActionContainerItem {
             params.put(Template.NAME, dbName.substring(1)) ;
         else
             params.put(Template.NAME, dbName) ;
-        FusekiServer.addGlobals(params); 
+        FusekiSystem.addGlobals(params); 
         
         //action.log.info(format("[%d] Create database : name = %s, type = %s", action.id, dbName, dbType )) ;
         if ( ! dbType.equals(tDatabasetTDB) && ! dbType.equals(tDatabasetMem) )
@@ -340,7 +340,7 @@ public class ActionDatasets extends ActionContainerItem {
             action.getDataAccessPointRegistry().remove(name) ;
             // Delete configuration file.
             // Should be only one, undo damage if multiple.
-            FusekiEnv.existingConfigurationFile(name).stream().forEach(FileOps::deleteSilent);
+            FusekiSystem.existingConfigurationFile(name).stream().forEach(FileOps::deleteSilent);
             
             // Find graph associated with this dataset name.
             // (Statically configured databases aren't in the system database.)

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
index 1befcd7..8c9a125 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
@@ -27,7 +27,7 @@ import org.apache.jena.atlas.lib.DateTimeUtils ;
 import org.apache.jena.atlas.logging.Log ;
 import org.apache.jena.fuseki.Fuseki ;
 import org.apache.jena.fuseki.FusekiException ;
-import org.apache.jena.fuseki.server.FusekiServer ;
+import org.apache.jena.fuseki.server.FusekiSystem ;
 import org.apache.jena.query.ReadWrite ;
 import org.apache.jena.riot.Lang ;
 import org.apache.jena.riot.RDFDataMgr ;
@@ -52,7 +52,7 @@ public class Backup
 
         String timestamp = DateTimeUtils.nowAsString("yyyy-MM-dd_HH-mm-ss") ;
         String filename = ds + "_" + timestamp ;
-        filename = FusekiServer.dirBackups.resolve(filename).toString() ;
+        filename = FusekiSystem.dirBackups.resolve(filename).toString() ;
         return filename ;
     }
     

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
index 3799c9a..71195d5 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
@@ -18,26 +18,15 @@
 
 package org.apache.jena.fuseki.server;
 
-import static java.lang.String.format ;
-
-import java.io.IOException ;
-import java.nio.file.DirectoryStream ;
-import java.nio.file.Files ;
 import java.nio.file.Path ;
 import java.nio.file.Paths ;
-import java.util.ArrayList ;
-import java.util.List ;
-
-import org.apache.jena.atlas.lib.InternalErrorException ;
-import org.apache.jena.fuseki.servlets.HttpAction ;
-import org.apache.jena.fuseki.servlets.ServletOps ;
 
 /** 
  * Separate initialization for FUSEKI_HOME and FUSEKI_BASE so that 
- * Fusekilogging can use these values.
+ * FusekiLogging can use these values.
  * This code must not touch Jena.  
  * 
- * @see FusekiServer 
+ * @see FusekiSystem 
  */ 
 public class FusekiEnv {
     // Initialization logging happens via stdout/stderr directly.
@@ -175,45 +164,5 @@ public class FusekiEnv {
             x = System.getProperty(name) ;
         return x ;
     }
-    
-    /** Dataset set name to configuration file name. */
-    public static String datasetNameToConfigurationFile(HttpAction action, String dsName) {
-        List<String> existing = existingConfigurationFile(dsName) ;
-        if ( ! existing.isEmpty() ) {
-            if ( existing.size() > 1 ) {
-                action.log.warn(format("[%d] Multiple existing configuration files for %s : %s",
-                                       action.id, dsName, existing));
-                ServletOps.errorBadRequest("Multiple existing configuration files for "+dsName);
-                return null ;
-            }
-            return existing.get(0) ;
-        }
-        
-        return generateConfigurationFilename(dsName) ;
-    }
-
-    /** Choose a configuration file name - existing one or ".ttl" form if new */
-    public static String generateConfigurationFilename(String dsName) {
-        String filename = dsName ;
-        // Without "/"
-        if ( filename.startsWith("/"))
-            filename = filename.substring(1) ;
-        filename = FusekiServer.dirConfiguration.resolve(filename).toString()+".ttl" ;
-        return filename ;
-    }
-
-    /** Return the filenames of all matching files in the configuration directory */  
-    public static List<String> existingConfigurationFile(String baseFilename) {
-        try { 
-            List<String> paths = new ArrayList<>() ;
-            try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiServer.dirConfiguration, baseFilename+"*") ) {
-                stream.forEach((p)-> paths.add(p.getFileName().toString())) ;
-            }
-            return paths ;
-        } catch (IOException ex) {
-            throw new InternalErrorException("Failed to read configuration directory "+FusekiServer.dirConfiguration) ;
-        }
-    }
-
 }
 

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
deleted file mode 100644
index 1697f8f..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
+++ /dev/null
@@ -1,420 +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.server;
-
-import java.io.File ;
-import java.io.IOException ;
-import java.io.InputStream ;
-import java.io.StringReader ;
-import java.net.URL ;
-import java.nio.file.Files ;
-import java.nio.file.Path ;
-import java.nio.file.StandardCopyOption ;
-import java.util.* ;
-
-import jena.cmd.CmdException ;
-import org.apache.jena.atlas.io.IO ;
-import org.apache.jena.atlas.lib.FileOps ;
-import org.apache.jena.atlas.lib.InternalErrorException ;
-import org.apache.jena.fuseki.Fuseki ;
-import org.apache.jena.fuseki.FusekiConfigException ;
-import org.apache.jena.fuseki.build.* ;
-import org.apache.jena.fuseki.servlets.ServletOps ;
-import org.apache.jena.rdf.model.* ;
-import org.apache.jena.riot.Lang ;
-import org.apache.jena.riot.RDFDataMgr ;
-import org.apache.jena.riot.RDFLanguages ;
-import org.apache.jena.sparql.core.DatasetGraph ;
-import org.apache.jena.tdb.sys.Names ;
-
-public class FusekiServer
-{
-    // Initialization of FUSEKI_HOME and FUSEKI_BASE is done in FusekiEnv.setEnvironment()
-    // so that the code is independent of any logging.  FusekiLogging can use
-    // initialized values of FUSEKI_BASE while looking forlog4j configuration.
-    
-    /** 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 $FUSEKI_HOME/run.
-     * This is not null - it may be /etc/fuseki, which must be writable.
-     */ 
-    //public static Path FUSEKI_BASE = null ;
-    
-    // Relative names of directories in the FUSEKI_BASE area.
-    public static final String     runArea                  = FusekiEnv.ENV_runArea ;
-    public static final String     databasesLocationBase    = "databases" ;
-    // Place to put Lucene text and spatial indexes.
-    //private static final String        databaseIndexesDir       = "indexes" ;
-      
-    public static final String     backupDirNameBase        = "backups" ;
-    public static final String     configDirNameBase        = "configuration" ;
-    public static final String     logsNameBase             = "logs" ;
-    public static final String     systemDatabaseNameBase   = "system" ;
-    public static final String     systemFileAreaBase       = "system_files" ;
-    public static final String     templatesNameBase        = "templates" ;
-    // This name is in web.xml as well.
-    public static final String     DFT_SHIRO_INI            = "shiro.ini" ; 
-    // In FUSEKI_BASE
-    public static final String     DFT_CONFIG               = "config.ttl" ;
-    
-    /** Directory for TDB databases - this is known to the assembler templates */
-    public static Path        dirDatabases       = null ;
-    
-    /** Directory for writing backups */
-    public static Path        dirBackups         = null ;
-
-    /** Directory for assembler files */
-    public static Path        dirConfiguration   = null ;
-    
-    /** 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 assmbler descriptions); not data uploads. */
-    public static Path        dirFileArea        = null ;
-    
-    /** Directory for assembler files */
-    public static Path        dirTemplates       = null ;
-
-    private static boolean    initialized        = false ;
-    // Marks the end of successful initialization.
-    /*package*/static boolean serverInitialized  = false ;
-
-    /*package*/ synchronized static void formatBaseArea() {
-        if ( initialized )
-            return ;
-        initialized = true ;
-        try {
-            FusekiEnv.setEnvironment() ;
-            Path FUSEKI_HOME = FusekiEnv.FUSEKI_HOME ;
-            Path FUSEKI_BASE = FusekiEnv.FUSEKI_BASE ;
-            
-            Fuseki.init() ;
-            Fuseki.configLog.info("FUSEKI_HOME="+ ((FUSEKI_HOME==null) ? "unset" : FUSEKI_HOME.toString())) ;
-            Fuseki.configLog.info("FUSEKI_BASE="+FUSEKI_BASE.toString());
-
-            // ----  Check FUSEKI_HOME and FUSEKI_BASE
-            // If FUSEKI_HOME exists, it may be FUSEKI_BASE.
-
-            if ( FUSEKI_HOME != null ) {
-                if ( ! Files.isDirectory(FUSEKI_HOME) )
-                    throw new FusekiConfigException("FUSEKI_HOME is not a directory: "+FUSEKI_HOME) ;
-                if ( ! Files.isReadable(FUSEKI_HOME) )
-                    throw new FusekiConfigException("FUSEKI_HOME is not readable: "+FUSEKI_HOME) ;
-            }
-
-            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) ;
-            } else {
-                ensureDir(FUSEKI_BASE);
-            }
-
-            // 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) ;
-            dirSystemDatabase   = writeableDirectory(FUSEKI_BASE, systemDatabaseNameBase) ;
-            dirFileArea         = writeableDirectory(FUSEKI_BASE, systemFileAreaBase) ;
-            //Possible intercept point
-
-            // ---- Initialize with files.
-
-            if ( Files.isRegularFile(FUSEKI_BASE) ) 
-                throw new FusekiConfigException("FUSEKI_BASE exists but is a file") ;
-
-            // Copy missing files into FUSEKI_BASE
-            copyFileIfMissing(null, DFT_SHIRO_INI, FUSEKI_BASE) ;
-            copyFileIfMissing(null, DFT_CONFIG, FUSEKI_BASE) ;
-            for ( String n : Template.templateNames ) {
-                copyFileIfMissing(null, n, FUSEKI_BASE) ;
-            }
-
-            serverInitialized = true ;
-        } catch (RuntimeException ex) {
-            Fuseki.serverLog.error("Exception in server initialization", ex) ;
-            throw ex ;
-        }
-    }
-    
-    /** 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) {
-        
-        Path dstFile = dst.resolve(fn) ;
-        if ( Files.exists(dstFile) )
-            return ;
-        
-        // fn may be a path.
-        if ( src != null ) {
-            try {
-                Files.copy(src.resolve(fn), dstFile, StandardCopyOption.COPY_ATTRIBUTES) ;
-            } catch (IOException e) {
-                IO.exception("Failed to copy file "+src, e);
-                e.printStackTrace();
-            }
-        } else {
-            try {
-                // Get from the file from area "org/apache/jena/fuseki/server"  (our package)
-                URL url = FusekiServer.class.getResource(fn) ;
-                if ( url == null )
-                    throw new FusekiConfigException("Field to find resource '"+fn+"'") ; 
-                InputStream in = url.openStream() ;
-                Files.copy(in, dstFile) ;
-            }
-            catch (IOException e) {
-                IO.exception("Failed to copy file from resource: "+src, e);
-                e.printStackTrace();
-            }
-        }
-    }
-
-    public static void initializeDataAccessPoints(DataAccessPointRegistry registry, FusekiInitialConfig initialSetup, String configDir) {
-        List<DataAccessPoint> configFileDBs = initServerConfiguration(initialSetup) ;
-        List<DataAccessPoint> directoryDBs =  FusekiConfig.readConfigurationDirectory(configDir) ;
-        List<DataAccessPoint> systemDBs =     FusekiConfig.readSystemDatabase(SystemState.getDataset()) ;
-        
-        List<DataAccessPoint> datapoints = new ArrayList<>() ;
-        datapoints.addAll(configFileDBs) ;
-        datapoints.addAll(directoryDBs) ;
-        datapoints.addAll(systemDBs) ;
-        
-        // Having found them, set them all running.
-        enable(registry, datapoints);
-    }
-
-    private static void enable(DataAccessPointRegistry registry, List<DataAccessPoint> datapoints) {
-        for ( DataAccessPoint dap : datapoints ) {
-            Fuseki.configLog.info("Register: "+dap.getName()) ;
-            registry.register(dap.getName(), dap); 
-        }
-    }
-
-    private static List<DataAccessPoint> initServerConfiguration(FusekiInitialConfig params) { 
-        // Has a side effect of global context setting
-        // when processing a config file.
-        // Compatibility.
-        
-        List<DataAccessPoint> datasets = new ArrayList<>();
-        if ( params == null )
-            return datasets ;
-
-        if ( params.fusekiCmdLineConfigFile != null ) {
-            List<DataAccessPoint> confDatasets = processServerConfigFile(params.fusekiCmdLineConfigFile) ;
-            datasets.addAll(confDatasets) ;
-        }
-        else if ( params.fusekiServerConfigFile != null ) {
-            List<DataAccessPoint> confDatasets = processServerConfigFile(params.fusekiServerConfigFile) ;
-            datasets.addAll(confDatasets) ;
-        }
-        else if ( params.dsg != null ) {
-            DataAccessPoint dap = datasetDefaultConfiguration(params.datasetPath, params.dsg, params.allowUpdate) ;
-            datasets.add(dap) ;
-        } else if ( params.argTemplateFile != null ) {
-            DataAccessPoint dap = configFromTemplate(params.argTemplateFile, params.datasetPath, params.allowUpdate, params.params) ;
-            datasets.add(dap) ;
-        }
-        // No datasets is valid.
-        return datasets ;
-    }
-    
-    private static List<DataAccessPoint> processServerConfigFile(String configFilename) {
-        if ( ! FileOps.exists(configFilename) ) {
-            Fuseki.configLog.warn("Configuration file '" + configFilename+"' does not exist") ;
-            return Collections.emptyList(); 
-        }
-        Fuseki.configLog.info("Configuration file: " + configFilename) ;
-        return FusekiConfig.readServerConfigFile(configFilename) ;
-    }
-    
-    private static DataAccessPoint configFromTemplate(String templateFile, String datasetPath, 
-                                                      boolean allowUpdate, Map<String, String> params) {
-        DatasetDescriptionRegistry registry = FusekiServer.registryForBuild() ; 
-        // ---- Setup
-        if ( params == null ) {
-            params = new HashMap<>() ;
-            params.put(Template.NAME, datasetPath) ;
-        } else {
-            if ( ! params.containsKey(Template.NAME) ) {
-                Fuseki.configLog.warn("No NAME found in template parameters (added)") ;
-                params.put(Template.NAME, datasetPath) ;   
-            }
-        }
-        //-- Logging
-        Fuseki.configLog.info("Template file: " + templateFile) ;
-        String dir = params.get(Template.DIR) ;
-        if ( dir != null ) {
-            if ( Objects.equals(dir, Names.memName) ) {
-                Fuseki.configLog.info("TDB dataset: in-memory") ;
-            } else {
-                if ( !FileOps.exists(dir) )
-                    throw new CmdException("Directory not found: " + dir) ;
-                Fuseki.configLog.info("TDB dataset: directory=" + dir) ;
-            }
-        }
-        //-- Logging
-        
-        datasetPath = DataAccessPoint.canonical(datasetPath) ;
-        
-        // DRY -- ActionDatasets (and others?)
-        addGlobals(params); 
-
-        String str = TemplateFunctions.templateFile(templateFile, params, Lang.TTL) ;
-        Lang lang = RDFLanguages.filenameToLang(str, Lang.TTL) ;
-        StringReader sr =  new StringReader(str) ;
-        Model model = ModelFactory.createDefaultModel() ;
-        RDFDataMgr.read(model, sr, datasetPath, lang);
-        
-        // ---- DataAccessPoint
-        Statement stmt = getOne(model, null, FusekiVocab.pServiceName, null) ;
-        if ( stmt == null ) {
-            StmtIterator sIter = model.listStatements(null, FusekiVocab.pServiceName, (RDFNode)null ) ;
-            if ( ! sIter.hasNext() )
-                ServletOps.errorBadRequest("No name given in description of Fuseki service") ;
-            sIter.next() ;
-            if ( sIter.hasNext() )
-                ServletOps.errorBadRequest("Multiple names given in description of Fuseki service") ;
-            throw new InternalErrorException("Inconsistent: getOne didn't fail the second time") ;
-        }
-        Resource subject = stmt.getSubject() ;
-        if ( ! allowUpdate ) {
-            // Opportunity for more sophisticated "read-only" mode.
-            //  1 - clean model, remove "fu:serviceUpdate", "fu:serviceUpload", "fu:serviceReadGraphStore", "fu:serviceReadWriteGraphStore"
-            //  2 - set a flag on DataAccessPoint
-        }
-        DataAccessPoint dap = FusekiBuilder.buildDataAccessPoint(subject, registry) ;
-        return dap ;
-    }
-    
-    public static void addGlobals(Map<String, String> params) {
-        if ( params == null ) {
-            Fuseki.configLog.warn("FusekiServer.addGlobals : params is null", new Throwable()) ;
-            return ;
-        }
-        
-        if ( ! params.containsKey("FUSEKI_BASE") )
-            params.put("FUSEKI_BASE", pathStringOrElse(FusekiEnv.FUSEKI_BASE, "unset")) ;
-        if ( ! params.containsKey("FUSEKI_HOME") )
-            params.put("FUSEKI_HOME", pathStringOrElse(FusekiEnv.FUSEKI_HOME, "unset")) ;
-    }
-
-    private static String pathStringOrElse(Path path, String dft) {
-        if ( path == null )
-            return dft ;
-        return path.toString() ;
-    }
-    
-    // DRY -- ActionDatasets (and others?)
-    private static Statement getOne(Model m, Resource s, Property p, RDFNode o) {
-        StmtIterator iter = m.listStatements(s, p, o) ;
-        if ( ! iter.hasNext() )
-            return null ;
-        Statement stmt = iter.next() ;
-        if ( iter.hasNext() )
-            return null ;
-        return stmt ;
-    }
-    
-    private static DataAccessPoint datasetDefaultConfiguration( String name, DatasetGraph dsg, boolean allowUpdate) {
-        name = DataAccessPoint.canonical(name) ;
-        DataService ds = FusekiBuilder.buildDataService(dsg, allowUpdate) ;
-        DataAccessPoint dap = new DataAccessPoint(name, ds) ;
-        return dap ;
-    }
-    
-    // ---- Helpers
-
-    /** Ensure a directory exists, creating it if necessary.
-     */
-    private static void ensureDir(Path directory) {
-        File dir = directory.toFile() ;
-        if ( ! dir.exists() ) {
-            boolean b = dir.mkdirs() ;
-            if ( ! b )
-                throw new FusekiConfigException("Failed to create directory: "+directory) ;
-        }
-        else if ( ! dir.isDirectory())
-            throw new FusekiConfigException("Not a directory: "+directory) ;
-    }
-
-    private static void mustExist(Path directory) {
-        File dir = directory.toFile() ;
-        if ( ! dir.exists() )
-            throw new FusekiConfigException("Does not exist: "+directory) ; 
-        if ( ! dir.isDirectory())
-            throw new FusekiConfigException("Not a directory: "+directory) ;
-    }
-    
-    private static boolean emptyDir(Path dir) {
-        return dir.toFile().list().length <= 2 ;
-    }
-    
-    private static boolean exists(Path directory) {
-        File dir = directory.toFile() ;
-        return dir.exists() ;
-    }
-
-    private static Path writeableDirectory(Path root , String relName ) {
-        Path p = makePath(root, relName) ;
-        ensureDir(p);
-        if ( ! Files.isWritable(p) )
-            throw new FusekiConfigException("Not writable: "+p) ;
-        return p ;
-    }
-    
-    private static Path makePath(Path root , String relName ) {
-        Path path = root.resolve(relName) ;
-        // Must exist
-//        try { path = path.toRealPath() ; }
-//        catch (IOException e) { IO.exception(e) ; }
-        return path ;
-    }
-
-    /**
-     * <ul>
-     * <li>GLOBAL: sharing across all descriptions
-     * <li>FILE: sharing within files but not across files.
-     * </ul>
-     */
-    enum DatasetDescriptionScope { GLOBAL, FILE }
-    private static DatasetDescriptionRegistry globalDatasets = new DatasetDescriptionRegistry() ;
-    private static DatasetDescriptionScope policyDatasetDescriptionScope = DatasetDescriptionScope.FILE ;
-    
-    /** Call this once per configuration file. */
-    public static DatasetDescriptionRegistry registryForBuild() {
-        switch (policyDatasetDescriptionScope) {
-            case FILE :     return new DatasetDescriptionRegistry() ;
-            case GLOBAL :   return globalDatasets ;
-            default:        throw new InternalErrorException() ;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
index 10e7ba3..ebf9f3d 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
@@ -70,8 +70,8 @@ public class FusekiServerListener implements ServletContextListener {
         DataAccessPointRegistry.set(servletContext, registry);
         
         try {
-            FusekiServer.formatBaseArea() ; 
-            if ( ! FusekiServer.serverInitialized ) {
+            FusekiSystem.formatBaseArea() ; 
+            if ( ! FusekiSystem.serverInitialized ) {
                 Fuseki.serverLog.error("Failed to initialize : Server not running") ;
                 return ;
             }
@@ -80,13 +80,13 @@ public class FusekiServerListener implements ServletContextListener {
             // In a non-commandline startup, initialSetup is null. 
             if ( initialSetup == null ) {
                 initialSetup = new FusekiInitialConfig() ;
-                String cfg = FusekiEnv.FUSEKI_BASE.resolve(FusekiServer.DFT_CONFIG).toAbsolutePath().toString() ;
+                String cfg = FusekiEnv.FUSEKI_BASE.resolve(FusekiSystem.DFT_CONFIG).toAbsolutePath().toString() ;
                 initialSetup.fusekiServerConfigFile = cfg ;
             }
 
             if ( initialSetup != null ) {
-                FusekiServer.initializeDataAccessPoints(registry,
-                                                        initialSetup, FusekiServer.dirConfiguration.toString()) ;
+                FusekiSystem.initializeDataAccessPoints(registry,
+                                                        initialSetup, FusekiSystem.dirConfiguration.toString()) ;
             } else {
                 Fuseki.serverLog.error("No configuration") ;
                 throw new FusekiException("No configuration") ;

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiSystem.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiSystem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiSystem.java
new file mode 100644
index 0000000..3b5b19d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiSystem.java
@@ -0,0 +1,463 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.server;
+
+import static java.lang.String.format ;
+
+import java.io.File ;
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.StringReader ;
+import java.net.URL ;
+import java.nio.file.DirectoryStream ;
+import java.nio.file.Files ;
+import java.nio.file.Path ;
+import java.nio.file.StandardCopyOption ;
+import java.util.* ;
+
+import jena.cmd.CmdException ;
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.FusekiConfigException ;
+import org.apache.jena.fuseki.build.* ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.rdf.model.* ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.tdb.sys.Names ;
+
+public class FusekiSystem
+{
+    // Initialization of FUSEKI_HOME and FUSEKI_BASE is done in FusekiEnv.setEnvironment()
+    // so that the code is independent of any logging.  FusekiLogging can use
+    // initialized values of FUSEKI_BASE while looking forlog4j configuration.
+    
+    /* * 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 $FUSEKI_HOME/run.
+     * This is not null - it may be /etc/fuseki, which must be writable.
+     */ 
+    //public static Path FUSEKI_BASE = null ;
+    
+    // Relative names of directories in the FUSEKI_BASE area.
+    public static final String     runArea                  = FusekiEnv.ENV_runArea ;
+    public static final String     databasesLocationBase    = "databases" ;
+    // Place to put Lucene text and spatial indexes.
+    //private static final String        databaseIndexesDir       = "indexes" ;
+      
+    public static final String     backupDirNameBase        = "backups" ;
+    public static final String     configDirNameBase        = "configuration" ;
+    public static final String     logsNameBase             = "logs" ;
+    public static final String     systemDatabaseNameBase   = "system" ;
+    public static final String     systemFileAreaBase       = "system_files" ;
+    public static final String     templatesNameBase        = "templates" ;
+    // This name is in web.xml as well.
+    public static final String     DFT_SHIRO_INI            = "shiro.ini" ; 
+    // In FUSEKI_BASE
+    public static final String     DFT_CONFIG               = "config.ttl" ;
+    
+    /** Directory for TDB databases - this is known to the assembler templates */
+    public static Path        dirDatabases       = null ;
+    
+    /** Directory for writing backups */
+    public static Path        dirBackups         = null ;
+
+    /** Directory for assembler files */
+    public static Path        dirConfiguration   = null ;
+    
+    /** 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 assmbler descriptions); not data uploads. */
+    public static Path        dirFileArea        = null ;
+    
+    /** Directory for assembler files */
+    public static Path        dirTemplates       = null ;
+
+    private static boolean    initialized        = false ;
+    // Marks the end of successful initialization.
+    /*package*/static boolean serverInitialized  = false ;
+
+    /*package*/ synchronized static void formatBaseArea() {
+        if ( initialized )
+            return ;
+        initialized = true ;
+        try {
+            FusekiEnv.setEnvironment() ;
+            Path FUSEKI_HOME = FusekiEnv.FUSEKI_HOME ;
+            Path FUSEKI_BASE = FusekiEnv.FUSEKI_BASE ;
+            
+            Fuseki.init() ;
+            Fuseki.configLog.info("FUSEKI_HOME="+ ((FUSEKI_HOME==null) ? "unset" : FUSEKI_HOME.toString())) ;
+            Fuseki.configLog.info("FUSEKI_BASE="+FUSEKI_BASE.toString());
+
+            // ----  Check FUSEKI_HOME and FUSEKI_BASE
+            // If FUSEKI_HOME exists, it may be FUSEKI_BASE.
+
+            if ( FUSEKI_HOME != null ) {
+                if ( ! Files.isDirectory(FUSEKI_HOME) )
+                    throw new FusekiConfigException("FUSEKI_HOME is not a directory: "+FUSEKI_HOME) ;
+                if ( ! Files.isReadable(FUSEKI_HOME) )
+                    throw new FusekiConfigException("FUSEKI_HOME is not readable: "+FUSEKI_HOME) ;
+            }
+
+            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) ;
+            } else {
+                ensureDir(FUSEKI_BASE);
+            }
+
+            // 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) ;
+            dirSystemDatabase   = writeableDirectory(FUSEKI_BASE, systemDatabaseNameBase) ;
+            dirFileArea         = writeableDirectory(FUSEKI_BASE, systemFileAreaBase) ;
+            //Possible intercept point
+
+            // ---- Initialize with files.
+
+            if ( Files.isRegularFile(FUSEKI_BASE) ) 
+                throw new FusekiConfigException("FUSEKI_BASE exists but is a file") ;
+
+            // Copy missing files into FUSEKI_BASE
+            copyFileIfMissing(null, DFT_SHIRO_INI, FUSEKI_BASE) ;
+            copyFileIfMissing(null, DFT_CONFIG, FUSEKI_BASE) ;
+            for ( String n : Template.templateNames ) {
+                copyFileIfMissing(null, n, FUSEKI_BASE) ;
+            }
+
+            serverInitialized = true ;
+        } catch (RuntimeException ex) {
+            Fuseki.serverLog.error("Exception in server initialization", ex) ;
+            throw ex ;
+        }
+    }
+    
+    /** 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) {
+        
+        Path dstFile = dst.resolve(fn) ;
+        if ( Files.exists(dstFile) )
+            return ;
+        
+        // fn may be a path.
+        if ( src != null ) {
+            try {
+                Files.copy(src.resolve(fn), dstFile, StandardCopyOption.COPY_ATTRIBUTES) ;
+            } catch (IOException e) {
+                IO.exception("Failed to copy file "+src, e);
+                e.printStackTrace();
+            }
+        } else {
+            try {
+                // Get from the file from area "org/apache/jena/fuseki/server"  (our package)
+                URL url = FusekiSystem.class.getResource(fn) ;
+                if ( url == null )
+                    throw new FusekiConfigException("Field to find resource '"+fn+"'") ; 
+                InputStream in = url.openStream() ;
+                Files.copy(in, dstFile) ;
+            }
+            catch (IOException e) {
+                IO.exception("Failed to copy file from resource: "+src, e);
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static void initializeDataAccessPoints(DataAccessPointRegistry registry, FusekiInitialConfig initialSetup, String configDir) {
+        List<DataAccessPoint> configFileDBs = initServerConfiguration(initialSetup) ;
+        List<DataAccessPoint> directoryDBs =  FusekiConfig.readConfigurationDirectory(configDir) ;
+        List<DataAccessPoint> systemDBs =     FusekiConfig.readSystemDatabase(SystemState.getDataset()) ;
+        
+        List<DataAccessPoint> datapoints = new ArrayList<>() ;
+        datapoints.addAll(configFileDBs) ;
+        datapoints.addAll(directoryDBs) ;
+        datapoints.addAll(systemDBs) ;
+        
+        // Having found them, set them all running.
+        enable(registry, datapoints);
+    }
+
+    private static void enable(DataAccessPointRegistry registry, List<DataAccessPoint> datapoints) {
+        for ( DataAccessPoint dap : datapoints ) {
+            Fuseki.configLog.info("Register: "+dap.getName()) ;
+            registry.register(dap.getName(), dap); 
+        }
+    }
+
+    private static List<DataAccessPoint> initServerConfiguration(FusekiInitialConfig params) { 
+        // Has a side effect of global context setting
+        // when processing a config file.
+        // Compatibility.
+        
+        List<DataAccessPoint> datasets = new ArrayList<>();
+        if ( params == null )
+            return datasets ;
+
+        if ( params.fusekiCmdLineConfigFile != null ) {
+            List<DataAccessPoint> confDatasets = processServerConfigFile(params.fusekiCmdLineConfigFile) ;
+            datasets.addAll(confDatasets) ;
+        }
+        else if ( params.fusekiServerConfigFile != null ) {
+            List<DataAccessPoint> confDatasets = processServerConfigFile(params.fusekiServerConfigFile) ;
+            datasets.addAll(confDatasets) ;
+        }
+        else if ( params.dsg != null ) {
+            DataAccessPoint dap = datasetDefaultConfiguration(params.datasetPath, params.dsg, params.allowUpdate) ;
+            datasets.add(dap) ;
+        } else if ( params.argTemplateFile != null ) {
+            DataAccessPoint dap = configFromTemplate(params.argTemplateFile, params.datasetPath, params.allowUpdate, params.params) ;
+            datasets.add(dap) ;
+        }
+        // No datasets is valid.
+        return datasets ;
+    }
+    
+    private static List<DataAccessPoint> processServerConfigFile(String configFilename) {
+        if ( ! FileOps.exists(configFilename) ) {
+            Fuseki.configLog.warn("Configuration file '" + configFilename+"' does not exist") ;
+            return Collections.emptyList(); 
+        }
+        Fuseki.configLog.info("Configuration file: " + configFilename) ;
+        return FusekiConfig.readServerConfigFile(configFilename) ;
+    }
+    
+    private static DataAccessPoint configFromTemplate(String templateFile, String datasetPath, 
+                                                      boolean allowUpdate, Map<String, String> params) {
+        DatasetDescriptionRegistry registry = FusekiSystem.registryForBuild() ; 
+        // ---- Setup
+        if ( params == null ) {
+            params = new HashMap<>() ;
+            params.put(Template.NAME, datasetPath) ;
+        } else {
+            if ( ! params.containsKey(Template.NAME) ) {
+                Fuseki.configLog.warn("No NAME found in template parameters (added)") ;
+                params.put(Template.NAME, datasetPath) ;   
+            }
+        }
+        //-- Logging
+        Fuseki.configLog.info("Template file: " + templateFile) ;
+        String dir = params.get(Template.DIR) ;
+        if ( dir != null ) {
+            if ( Objects.equals(dir, Names.memName) ) {
+                Fuseki.configLog.info("TDB dataset: in-memory") ;
+            } else {
+                if ( !FileOps.exists(dir) )
+                    throw new CmdException("Directory not found: " + dir) ;
+                Fuseki.configLog.info("TDB dataset: directory=" + dir) ;
+            }
+        }
+        //-- Logging
+        
+        datasetPath = DataAccessPoint.canonical(datasetPath) ;
+        
+        // DRY -- ActionDatasets (and others?)
+        addGlobals(params); 
+
+        String str = TemplateFunctions.templateFile(templateFile, params, Lang.TTL) ;
+        Lang lang = RDFLanguages.filenameToLang(str, Lang.TTL) ;
+        StringReader sr =  new StringReader(str) ;
+        Model model = ModelFactory.createDefaultModel() ;
+        RDFDataMgr.read(model, sr, datasetPath, lang);
+        
+        // ---- DataAccessPoint
+        Statement stmt = getOne(model, null, FusekiVocab.pServiceName, null) ;
+        if ( stmt == null ) {
+            StmtIterator sIter = model.listStatements(null, FusekiVocab.pServiceName, (RDFNode)null ) ;
+            if ( ! sIter.hasNext() )
+                ServletOps.errorBadRequest("No name given in description of Fuseki service") ;
+            sIter.next() ;
+            if ( sIter.hasNext() )
+                ServletOps.errorBadRequest("Multiple names given in description of Fuseki service") ;
+            throw new InternalErrorException("Inconsistent: getOne didn't fail the second time") ;
+        }
+        Resource subject = stmt.getSubject() ;
+        if ( ! allowUpdate ) {
+            // Opportunity for more sophisticated "read-only" mode.
+            //  1 - clean model, remove "fu:serviceUpdate", "fu:serviceUpload", "fu:serviceReadGraphStore", "fu:serviceReadWriteGraphStore"
+            //  2 - set a flag on DataAccessPoint
+        }
+        DataAccessPoint dap = FusekiBuilder.buildDataAccessPoint(subject, registry) ;
+        return dap ;
+    }
+    
+    public static void addGlobals(Map<String, String> params) {
+        if ( params == null ) {
+            Fuseki.configLog.warn("FusekiServer.addGlobals : params is null", new Throwable()) ;
+            return ;
+        }
+        
+        if ( ! params.containsKey("FUSEKI_BASE") )
+            params.put("FUSEKI_BASE", pathStringOrElse(FusekiEnv.FUSEKI_BASE, "unset")) ;
+        if ( ! params.containsKey("FUSEKI_HOME") )
+            params.put("FUSEKI_HOME", pathStringOrElse(FusekiEnv.FUSEKI_HOME, "unset")) ;
+    }
+
+    private static String pathStringOrElse(Path path, String dft) {
+        if ( path == null )
+            return dft ;
+        return path.toString() ;
+    }
+    
+    // DRY -- ActionDatasets (and others?)
+    private static Statement getOne(Model m, Resource s, Property p, RDFNode o) {
+        StmtIterator iter = m.listStatements(s, p, o) ;
+        if ( ! iter.hasNext() )
+            return null ;
+        Statement stmt = iter.next() ;
+        if ( iter.hasNext() )
+            return null ;
+        return stmt ;
+    }
+    
+    private static DataAccessPoint datasetDefaultConfiguration( String name, DatasetGraph dsg, boolean allowUpdate) {
+        name = DataAccessPoint.canonical(name) ;
+        DataService ds = FusekiBuilder.buildDataService(dsg, allowUpdate) ;
+        DataAccessPoint dap = new DataAccessPoint(name, ds) ;
+        return dap ;
+    }
+    
+    // ---- Helpers
+
+    /** Ensure a directory exists, creating it if necessary.
+     */
+    private static void ensureDir(Path directory) {
+        File dir = directory.toFile() ;
+        if ( ! dir.exists() ) {
+            boolean b = dir.mkdirs() ;
+            if ( ! b )
+                throw new FusekiConfigException("Failed to create directory: "+directory) ;
+        }
+        else if ( ! dir.isDirectory())
+            throw new FusekiConfigException("Not a directory: "+directory) ;
+    }
+
+    private static void mustExist(Path directory) {
+        File dir = directory.toFile() ;
+        if ( ! dir.exists() )
+            throw new FusekiConfigException("Does not exist: "+directory) ; 
+        if ( ! dir.isDirectory())
+            throw new FusekiConfigException("Not a directory: "+directory) ;
+    }
+    
+    private static boolean emptyDir(Path dir) {
+        return dir.toFile().list().length <= 2 ;
+    }
+    
+    private static boolean exists(Path directory) {
+        File dir = directory.toFile() ;
+        return dir.exists() ;
+    }
+
+    private static Path writeableDirectory(Path root , String relName ) {
+        Path p = makePath(root, relName) ;
+        ensureDir(p);
+        if ( ! Files.isWritable(p) )
+            throw new FusekiConfigException("Not writable: "+p) ;
+        return p ;
+    }
+    
+    private static Path makePath(Path root , String relName ) {
+        Path path = root.resolve(relName) ;
+        // Must exist
+//        try { path = path.toRealPath() ; }
+//        catch (IOException e) { IO.exception(e) ; }
+        return path ;
+    }
+
+    /**
+     * <ul>
+     * <li>GLOBAL: sharing across all descriptions
+     * <li>FILE: sharing within files but not across files.
+     * </ul>
+     */
+    enum DatasetDescriptionScope { GLOBAL, FILE }
+    private static DatasetDescriptionRegistry globalDatasets = new DatasetDescriptionRegistry() ;
+    private static DatasetDescriptionScope policyDatasetDescriptionScope = DatasetDescriptionScope.FILE ;
+    
+    /** Call this once per configuration file. */
+    public static DatasetDescriptionRegistry registryForBuild() {
+        switch (policyDatasetDescriptionScope) {
+            case FILE :     return new DatasetDescriptionRegistry() ;
+            case GLOBAL :   return globalDatasets ;
+            default:        throw new InternalErrorException() ;
+        }
+    }
+    
+    /** Dataset set name to configuration file name. */
+    public static String datasetNameToConfigurationFile(HttpAction action, String dsName) {
+        List<String> existing = existingConfigurationFile(dsName) ;
+        if ( ! existing.isEmpty() ) {
+            if ( existing.size() > 1 ) {
+                action.log.warn(format("[%d] Multiple existing configuration files for %s : %s",
+                                       action.id, dsName, existing));
+                ServletOps.errorBadRequest("Multiple existing configuration files for "+dsName);
+                return null ;
+            }
+            return existing.get(0) ;
+        }
+        
+        return generateConfigurationFilename(dsName) ;
+    }
+
+    /** Choose a configuration file name - existing one or ".ttl" form if new */
+    public static String generateConfigurationFilename(String dsName) {
+        String filename = dsName ;
+        // Without "/"
+        if ( filename.startsWith("/"))
+            filename = filename.substring(1) ;
+        filename = FusekiSystem.dirConfiguration.resolve(filename).toString()+".ttl" ;
+        return filename ;
+    }
+
+    /** Return the filenames of all matching files in the configuration directory */  
+    public static List<String> existingConfigurationFile(String baseFilename) {
+        try { 
+            List<String> paths = new ArrayList<>() ;
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(FusekiSystem.dirConfiguration, baseFilename+"*") ) {
+                stream.forEach((p)-> paths.add(p.getFileName().toString())) ;
+            }
+            return paths ;
+        } catch (IOException ex) {
+            throw new InternalErrorException("Failed to read configuration directory "+FusekiSystem.dirConfiguration) ;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ShiroEnvironmentLoader.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ShiroEnvironmentLoader.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ShiroEnvironmentLoader.java
index f963e8e..03d7c1c 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ShiroEnvironmentLoader.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/ShiroEnvironmentLoader.java
@@ -47,7 +47,7 @@ public class ShiroEnvironmentLoader extends EnvironmentLoader implements Servlet
     
     @Override
     public void contextInitialized(ServletContextEvent sce) {
-        FusekiServer.formatBaseArea() ; 
+        FusekiSystem.formatBaseArea() ; 
         this.servletContext = sce.getServletContext() ;
         try { 
             // Shiro.

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/SystemState.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/SystemState.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/SystemState.java
index 9959d26..460fda1 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/SystemState.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/SystemState.java
@@ -75,7 +75,7 @@ public class SystemState {
         initialized = true ;
         
         if ( location == null )
-            location = Location.create(FusekiServer.dirSystemDatabase.toString()) ;
+            location = Location.create(FusekiSystem.dirSystemDatabase.toString()) ;
         
         if ( ! location.isMem() )
             FileOps.ensureDir(location.getDirectoryPath()) ;

http://git-wip-us.apache.org/repos/asf/jena/blob/1e6afdd4/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
index ce96867..e9fbc05 100644
--- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/ServerCtl.java
@@ -248,7 +248,7 @@ public class ServerCtl {
         if ( server != null ) {
             // Clear out the registry.
             server.getDataAccessPointRegistry().clear() ;
-            FileOps.clearAll(FusekiServer.dirConfiguration.toFile()) ;
+            FileOps.clearAll(FusekiSystem.dirConfiguration.toFile()) ;
             server.stop() ;
         }
         server = null ;


[2/3] jena git commit: JENA-1371: Rename FusekiEmbeddedServer as FusekiServer

Posted by an...@apache.org.
JENA-1371: Rename FusekiEmbeddedServer as FusekiServer


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/2e579e38
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/2e579e38
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/2e579e38

Branch: refs/heads/master
Commit: 2e579e3811a6af296e539eef622b9dd811630970
Parents: 1e6afdd
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Jul 7 11:47:22 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Jul 7 11:47:22 2017 +0100

----------------------------------------------------------------------
 .../apache/jena/fuseki/cmds/FusekiBasicCmd.java |  10 +-
 .../fuseki/embedded/FusekiEmbeddedServer.java   | 333 +---------------
 .../jena/fuseki/embedded/FusekiServer.java      | 390 +++++++++++++++++++
 .../jena/fuseki/embedded/FusekiTestAuth.java    |   4 +-
 .../jena/fuseki/embedded/FusekiTestServer.java  |   8 +-
 .../fuseki/embedded/TestEmbeddedFuseki.java     |  22 +-
 .../fuseki/embedded/TestMultipleEmbedded.java   |  16 +-
 .../rdfconnection/TestRDFConnectionRemote.java  |   6 +-
 8 files changed, 442 insertions(+), 347 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
index 8229a0b..17fb51e 100644
--- a/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
+++ b/jena-fuseki2/jena-fuseki-basic/src/main/java/org/apache/jena/fuseki/cmds/FusekiBasicCmd.java
@@ -37,7 +37,7 @@ import org.apache.jena.atlas.lib.FileOps;
 import org.apache.jena.atlas.logging.FmtLog;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiLogging;
-import org.apache.jena.fuseki.embedded.FusekiEmbeddedServer;
+import org.apache.jena.fuseki.embedded.FusekiServer;
 import org.apache.jena.fuseki.server.DataAccessPoint;
 import org.apache.jena.fuseki.server.DataAccessPointRegistry;
 import org.apache.jena.fuseki.server.DataService;
@@ -357,7 +357,7 @@ public class FusekiBasicCmd {
         @Override
         protected void exec() {
             try {
-                FusekiEmbeddedServer server = buildServer(serverConfig);
+                FusekiServer server = buildServer(serverConfig);
                 info(server, serverConfig);
                 server.start();
                 server.join();
@@ -372,8 +372,8 @@ public class FusekiBasicCmd {
         }
 
         // ServerConfig -> Setup the builder.
-        private static FusekiEmbeddedServer buildServer(ServerConfig serverConfig) {
-            FusekiEmbeddedServer.Builder builder = FusekiEmbeddedServer.create();
+        private static FusekiServer buildServer(ServerConfig serverConfig) {
+            FusekiServer.Builder builder = FusekiServer.create();
             // Loopback.
             builder.setPort(serverConfig.port);
             builder.setLoopback(serverConfig.loopback);
@@ -401,7 +401,7 @@ public class FusekiBasicCmd {
             return builder.build();
         }
 
-        private void info(FusekiEmbeddedServer server, ServerConfig serverConfig) {
+        private void info(FusekiServer server, ServerConfig serverConfig) {
             if ( super.isQuiet() )
                 return;
 

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiEmbeddedServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiEmbeddedServer.java b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiEmbeddedServer.java
index 5ff5c74..8462d1e 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiEmbeddedServer.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiEmbeddedServer.java
@@ -18,95 +18,34 @@
 
 package org.apache.jena.fuseki.embedded;
 
-import java.util.ArrayList;
-import java.util.HashMap ;
-import java.util.List ;
-import java.util.Map ;
-
 import javax.servlet.ServletContext ;
-import javax.servlet.http.HttpServlet;
 
-import org.apache.jena.atlas.lib.Pair;
-import org.apache.jena.fuseki.Fuseki ;
-import org.apache.jena.fuseki.FusekiConfigException ;
-import org.apache.jena.fuseki.FusekiException ;
-import org.apache.jena.fuseki.build.FusekiBuilder ;
-import org.apache.jena.fuseki.build.FusekiConfig ;
-import org.apache.jena.fuseki.jetty.FusekiErrorHandler1 ;
-import org.apache.jena.fuseki.mgt.ActionStats ;
-import org.apache.jena.fuseki.server.DataAccessPoint ;
 import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
-import org.apache.jena.fuseki.server.DataService ;
-import org.apache.jena.fuseki.servlets.FusekiFilter ;
-import org.apache.jena.query.Dataset ;
-import org.apache.jena.riot.WebContent;
 import org.apache.jena.sparql.core.DatasetGraph ;
-import org.eclipse.jetty.http.MimeTypes;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.server.HttpConnectionFactory ;
 import org.eclipse.jetty.server.Server ;
-import org.eclipse.jetty.server.ServerConnector ;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.FilterHolder ;
-import org.eclipse.jetty.servlet.ServletContextHandler ;
-import org.eclipse.jetty.servlet.ServletHolder;
 
 /**
- * Embedded Fuseki server. This is a Fuseki server running with a precofigured set of
- * datasets and services. 
- * There is no admin UI.
- * <p>
- * To create a embedded sever, use {@link FusekiEmbeddedServer} ({@link #make} is a
- * packaging of a call to {@link FusekiEmbeddedServer} for the case of one dataset,
- * responding to localhost only).
- * <p>
- * The application should call {@link #start()} to actually start the server
- * (it wil run in the background : see {@link #join}).
- * <p>Example:
- * <pre>
- *      DatasetGraph dsg = ... ;
- *      FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
- *          .setPort(1234)
- *          .add("/ds", dsg)
- *          .build() ;
- *       server.start() ;
- * </pre>
- * Compact form (use the builder pattern above to get more flexibility):
- * <pre>
- *    FusekiEmbeddedServer.make(1234, "/ds", dsg).start() ;
- * </pre>
- * 
+ * Embedded Fuseki server.
+ * @deprecated Use {@link FusekiServer} 
  */
+@Deprecated
 public class FusekiEmbeddedServer {
-    static { 
-        //FusekiEnv.mode = FusekiEnv.INIT.EMBEDDED ;
-        // Stop anything accidently resetting Fuseki server logging. 
-        //FusekiLogging.allowLoggingReset(false) ;
-    }
-    
-    /** Construct a Fuseki server for one dataset.
-     * It only responds to localhost. 
-     * The returned server has not been started  */ 
+    /** @deprecated Use {@link FusekiServer#make} */  
+    @Deprecated
     static public FusekiEmbeddedServer make(int port, String name, DatasetGraph dsg) {
-        return create()
-            .setPort(port)
-            .setLoopback(true)
-            .add(name, dsg)
-            .build() ;
+        return new FusekiEmbeddedServer(FusekiServer.make(port, name, dsg));
     }
     
-    public static Builder create() {
-        return new Builder() ;
+    /** @deprecated Use {@link FusekiServer#create} */  
+    @Deprecated
+    public static FusekiServer.Builder create() {
+        return FusekiServer.create();
     }
     
-    public final Server server ;
-    private int port ;
+    private final FusekiServer server ;
     
-    private FusekiEmbeddedServer(int port, Server server) {
+    private FusekiEmbeddedServer(FusekiServer server) {
         this.server = server ;
-        // This should be the same.
-        //this.port = ((ServerConnector)server.getConnectors()[0]).getPort() ;
-        this.port = port ;
     }
     
     /** 
@@ -115,277 +54,43 @@ public class FusekiEmbeddedServer {
      * the one actually allocated if the port was 0 ("choose a free port").
      */
     public int getPort() {
-        return port ; 
+        return server.getPort();
     }
 
     /** Get the underlying Jetty server which has also been set up. */ 
     public Server getJettyServer() {
-        return server ; 
+        return server.getJettyServer();
     }
     
     /** Get the {@link ServletContext}.
      * Adding new servlets is possible with care.
      */ 
     public ServletContext getServletContext() {
-        return ((ServletContextHandler)server.getHandler()).getServletContext() ;
+        return server.getServletContext() ;
     }
 
     /** Get the {@link DataAccessPointRegistry}.
      * This method is intended for inspecting the registry.
      */ 
     public DataAccessPointRegistry getDataAccessPointRegistry() {
-        return DataAccessPointRegistry.get(getServletContext()) ;
+        return server.getDataAccessPointRegistry() ;
     }
 
     /** Start the server - the server continues to run after this call returns.
      *  To synchronise with the server stopping, call {@link #join}.  
      */
     public FusekiEmbeddedServer start() { 
-        try { server.start(); }
-        catch (Exception e) { throw new FusekiException(e) ; }
-        if ( port == 0 )
-            port = ((ServerConnector)server.getConnectors()[0]).getLocalPort() ;
-        Fuseki.serverLog.info("Start Fuseki (port="+port+")");
+        server.start();
         return this ;
     }
 
     /** Stop the server. */
     public void stop() { 
-        Fuseki.serverLog.info("Stop Fuseki (port="+port+")");
-        try { server.stop(); }
-        catch (Exception e) { throw new FusekiException(e) ; }
+        server.stop();
     }
     
     /** Wait for the server to exit. This call is blocking. */
     public void join() {
-        try { server.join(); }
-        catch (Exception e) { throw new FusekiException(e) ; }
-    }
-    
-    /** FusekiEmbeddedServer.Builder */
-    public static class Builder {
-        private Map<String, DataService> map                = new HashMap<>() ;
-        // Default values.
-        private int                      port               = 3330 ;
-        private boolean                  loopback           = false ;
-        private boolean                  withStats          = false ;
-        // Other servlets to add.
-        private List<Pair<String, HttpServlet>> other = new ArrayList<>();
-        private String                   contextPath        = "/" ;
-        private String                   staticContentDir   = null ;
-        private SecurityHandler          securityHandler    = null ;
-
-        /** Set the port to run on. */ 
-        public Builder setPort(int port) {
-            if ( port < 0 )
-                throw new IllegalArgumentException("Illegal port="+port+" : Port must be greater than or equal to zero.") ;
-            this.port = port ;
-            return this ;
-        }
-        
-        /** Context path to Fuseki.  If it's "/" then Fuseki URL look like
-         * "http://host:port/dataset/query" else "http://host:port/path/dataset/query" 
-         */
-        public Builder setContextPath(String path) {
-            this.contextPath = path ;
-            return this ;
-        }
-        
-        /** Restrict the server to only responding to the localhost interface. */ 
-        public Builder setLoopback(boolean loopback) {
-            this.loopback = loopback;
-            return this ;
-        }
-
-        /** Set the location (filing system directory) to serve static file from. */ 
-        public Builder setStaticFileBase(String directory) {
-            this.staticContentDir = directory;
-            return this ;
-        }
-        
-        /** Set a Jetty SecurityHandler.
-         *  By default, the server runs with no security.
-         *  This is more for using the basic server for testing.
-         *  The full Fuseki server provides secjurity with Apache Shiro
-         *  and a defensive reverse proxy (e.g. Apache httpd) in front og the Jetty server
-         *  can also be used, which provides a wide varient of proven security options.   
-         */
-        public Builder setSecurityHandler(SecurityHandler securityHandler) {
-            this.securityHandler = securityHandler;
-            return this;
-        }
-
-        /** Add the "/$/stats" servlet that responds with stats about the server,
-         * including counts of all calls made.
-         */ 
-        public Builder enableStats(boolean withStats) {
-            this.withStats = withStats;
-            return this ;
-        }
-
-        /** Add the dataset with given name and a default set of services including update */  
-        public Builder add(String name, Dataset ds) {
-            return add(name, ds.asDatasetGraph()) ;
-        }
-
-        /** Add the dataset with given name and a default set of services including update */  
-        public Builder add(String name, DatasetGraph dsg) {
-            return add(name, dsg, true) ;
-        }
-
-        /** Add the dataset with given name and a default set of services. */  
-        public Builder add(String name, Dataset ds, boolean allowUpdate) {
-            return add(name, ds.asDatasetGraph(), allowUpdate) ;
-        }
-        
-        /** Add the dataset with given name and a default set of services. */  
-        public Builder add(String name, DatasetGraph dsg, boolean allowUpdate) {
-            DataService dSrv = FusekiBuilder.buildDataService(dsg, allowUpdate) ; 
-            return add(name, dSrv) ;
-        }
-        
-        /** Add a data service that includes dataset and service names.
-         * A {@link DataService} allows for choices of the various endpoint names.
-         */  
-        public Builder add(String name, DataService dataService) {
-            return add$(name, dataService) ; 
-        }
-        
-        private Builder add$(String name, DataService dataService) {
-            name = DataAccessPoint.canonical(name) ;
-            if ( map.containsKey(name) )
-                throw new FusekiConfigException("Data service name already registered: "+name) ;
-            map.put(name, dataService) ;
-            return this ;
-        }
-
-        /** Read and parse a Fuseki services/datasets file.
-         *  <p>
-         *  The application is responsible for ensuring a correct classpath. For example,
-         *  including a dependency on {@code jena-text} if the configuration file
-         *  includes a text index.     
-         */
-        public Builder parseConfigFile(String filename) {
-            List<DataAccessPoint> x = FusekiConfig.readConfigurationFile(filename) ;
-            // Unbundle so that they accumulate.
-            x.forEach(dap-> add(dap.getName(), dap.getDataService())) ;
-            return this ;
-        }
-
-        /**
-         * Add the given servlet with the pathSpec. These are added so that they are
-         * checked after the Fuseki filter for datasets and before the static content
-         * handler (which is the last servlet) used for {@link #setStaticFileBase(String)}.
-         */
-        public Builder addServlet(String pathSpec, HttpServlet servlet) {
-            other.add(Pair.create(pathSpec, servlet));
-            return this;
-        }
-        
-        /** Build a server according to the current description */ 
-        public FusekiEmbeddedServer build() {
-            DataAccessPointRegistry registry = new DataAccessPointRegistry() ;
-            map.forEach((name, dSrv) -> {
-                DataAccessPoint dap = new DataAccessPoint(name, dSrv) ;
-                registry.put(name, dap) ;
-            }) ;
-            ServletContextHandler handler = buildServletContext(contextPath, registry) ;
-            
-            setMimeTypes(handler);
-            servlets(handler);
-            
-            DataAccessPointRegistry.set(handler.getServletContext(), registry) ;
-            Server server = jettyServer(port, loopback) ;
-            server.setHandler(handler);
-            return new FusekiEmbeddedServer(port, server) ;
-        }
-
-        /** Build a ServletContextHandler with the Fuseki router : {@link FusekiFilter} */
-        private ServletContextHandler buildServletContext(String contextPath, DataAccessPointRegistry registry) {
-            if ( contextPath == null || contextPath.isEmpty() )
-                contextPath = "/" ;
-            else if ( !contextPath.startsWith("/") )
-                contextPath = "/" + contextPath ;
-            ServletContextHandler context = new ServletContextHandler() ;
-            context.setDisplayName(Fuseki.servletRequestLogName) ;
-            context.setErrorHandler(new FusekiErrorHandler1()) ;
-            context.setContextPath(contextPath) ;
-            if ( securityHandler != null )
-                context.setSecurityHandler(securityHandler);
-            
-            return context ;
-        }
-        
-        private static void setMimeTypes(ServletContextHandler context) {
-            MimeTypes mimeTypes = new MimeTypes();
-            // RDF syntax
-            mimeTypes.addMimeMapping("nt",      WebContent.contentTypeNTriples);
-            mimeTypes.addMimeMapping("nq",      WebContent.contentTypeNQuads);
-            mimeTypes.addMimeMapping("ttl",     WebContent.contentTypeTurtle+";charset=utf-8");
-            mimeTypes.addMimeMapping("trig",    WebContent.contentTypeTriG+";charset=utf-8");
-            mimeTypes.addMimeMapping("rdfxml",  WebContent.contentTypeRDFXML);
-            mimeTypes.addMimeMapping("jsonld",  WebContent.contentTypeJSONLD);
-            mimeTypes.addMimeMapping("rj",      WebContent.contentTypeRDFJSON);
-            mimeTypes.addMimeMapping("rt",      WebContent.contentTypeRDFThrift);
-            mimeTypes.addMimeMapping("trdf",    WebContent.contentTypeRDFThrift);
-
-            // SPARQL syntax
-            mimeTypes.addMimeMapping("rq",      WebContent.contentTypeSPARQLQuery);
-            mimeTypes.addMimeMapping("ru",      WebContent.contentTypeSPARQLUpdate);
-
-            // SPARQL Result set
-            mimeTypes.addMimeMapping("rsj",     WebContent.contentTypeResultsJSON);
-            mimeTypes.addMimeMapping("rsx",     WebContent.contentTypeResultsXML);
-            mimeTypes.addMimeMapping("srt",     WebContent.contentTypeResultsThrift);
-
-            // Other
-            mimeTypes.addMimeMapping("txt",     WebContent.contentTypeTextPlain);
-            mimeTypes.addMimeMapping("csv",     WebContent.contentTypeTextCSV);
-            mimeTypes.addMimeMapping("tsv",     WebContent.contentTypeTextTSV);
-            context.setMimeTypes(mimeTypes);
-        }
-
-        private void servlets(ServletContextHandler context) {
-            // Fuseki dataset services filter
-            FusekiFilter ff = new FusekiFilter() ;
-            FilterHolder h = new FilterHolder(ff) ;
-            context.addFilter(h, "/*", null) ;
-
-            other.forEach(p->addServlet(context, p.getLeft(), p.getRight()));
-            
-            if ( withStats )
-                addServlet(context, "/$/stats", new ActionStats()) ;
-            
-            if ( staticContentDir != null ) {
-                DefaultServlet staticServlet = new DefaultServlet() ;
-                ServletHolder staticContent = new ServletHolder(staticServlet) ;
-                staticContent.setInitParameter("resourceBase", staticContentDir) ;
-                context.addServlet(staticContent, "/");
-            }
-                
-        }
-
-        private static void addServlet(ServletContextHandler context, String pathspec, HttpServlet httpServlet) {
-            ServletHolder sh = new ServletHolder(httpServlet);
-            context.addServlet(sh, pathspec) ;
-        }
-
-        /** Jetty server */
-        private static Server jettyServer(int port, boolean loopback) {
-            Server server = new Server() ;
-            HttpConnectionFactory f1 = new HttpConnectionFactory() ;
-            // Some people do try very large operations ... really, should use POST.
-            f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
-            f1.getHttpConfiguration().setOutputBufferSize(1024 * 1024) ;
-            // Do not add "Server: Jetty(....) when not a development system.
-            if ( ! Fuseki.outputJettyServerHeader )
-                f1.getHttpConfiguration().setSendServerVersion(false) ;
-            ServerConnector connector = new ServerConnector(server, f1) ;
-            connector.setPort(port) ;
-            server.addConnector(connector);
-            if ( loopback )
-                connector.setHost("localhost");
-            return server ;
-        }
+        server.join();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
new file mode 100644
index 0000000..5e9e887
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-embedded/src/main/java/org/apache/jena/fuseki/embedded/FusekiServer.java
@@ -0,0 +1,390 @@
+/*
+ * 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.embedded;
+
+import java.util.ArrayList;
+import java.util.HashMap ;
+import java.util.List ;
+import java.util.Map ;
+
+import javax.servlet.ServletContext ;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.jena.atlas.lib.Pair;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.FusekiConfigException ;
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.fuseki.build.FusekiBuilder ;
+import org.apache.jena.fuseki.build.FusekiConfig ;
+import org.apache.jena.fuseki.jetty.FusekiErrorHandler1 ;
+import org.apache.jena.fuseki.mgt.ActionStats ;
+import org.apache.jena.fuseki.server.DataAccessPoint ;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.server.DataService ;
+import org.apache.jena.fuseki.servlets.FusekiFilter ;
+import org.apache.jena.query.Dataset ;
+import org.apache.jena.riot.WebContent;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.server.HttpConnectionFactory ;
+import org.eclipse.jetty.server.Server ;
+import org.eclipse.jetty.server.ServerConnector ;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.FilterHolder ;
+import org.eclipse.jetty.servlet.ServletContextHandler ;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+/**
+ * Embedded Fuseki server. This is a Fuseki server running with a precofigured set of
+ * datasets and services. There is no admin UI and no security.
+ * <p>
+ * To create a embedded sever, use {@link FusekiServer} ({@link #make} is a
+ * packaging of a call to {@link FusekiServer} for the case of one dataset,
+ * responding to localhost only).
+ * <p>
+ * The application should call {@link #start()} to actually start the server
+ * (it wil run in the background : see {@link #join}).
+ * <p>Example:
+ * <pre>
+ *      DatasetGraph dsg = ... ;
+ *      FusekiServer server = FusekiServer.create()
+ *          .setPort(1234)
+ *          .add("/ds", dsg)
+ *          .build() ;
+ *       server.start() ;
+ * </pre>
+ * Compact form (use the builder pattern above to get more flexibility):
+ * <pre>
+ *    FusekiServer.make(1234, "/ds", dsg).start() ;
+ * </pre>
+ * 
+ */
+public class FusekiServer {
+    static { 
+        //FusekiEnv.mode = FusekiEnv.INIT.EMBEDDED ;
+        // Stop anything accidently resetting Fuseki server logging. 
+        //FusekiLogging.allowLoggingReset(false) ;
+    }
+    
+    /** Construct a Fuseki server for one dataset.
+     * It only responds to localhost. 
+     * The returned server has not been started  */ 
+    static public FusekiServer make(int port, String name, DatasetGraph dsg) {
+        return create()
+            .setPort(port)
+            .setLoopback(true)
+            .add(name, dsg)
+            .build() ;
+    }
+    
+    public static Builder create() {
+        return new Builder() ;
+    }
+    
+    public final Server server ;
+    private int port ;
+    
+    private FusekiServer(int port, Server server) {
+        this.server = server ;
+        // This should be the same.
+        //this.port = ((ServerConnector)server.getConnectors()[0]).getPort() ;
+        this.port = port ;
+    }
+    
+    /** 
+     * Return the port begin used.  
+     * This will be the give port, which defauls to 3330, or
+     * the one actually allocated if the port was 0 ("choose a free port").
+     */
+    public int getPort() {
+        return port ; 
+    }
+
+    /** Get the underlying Jetty server which has also been set up. */ 
+    public Server getJettyServer() {
+        return server ; 
+    }
+    
+    /** Get the {@link ServletContext}.
+     * Adding new servlets is possible with care.
+     */ 
+    public ServletContext getServletContext() {
+        return ((ServletContextHandler)server.getHandler()).getServletContext() ;
+    }
+
+    /** Get the {@link DataAccessPointRegistry}.
+     * This method is intended for inspecting the registry.
+     */ 
+    public DataAccessPointRegistry getDataAccessPointRegistry() {
+        return DataAccessPointRegistry.get(getServletContext()) ;
+    }
+
+    /** Start the server - the server continues to run after this call returns.
+     *  To synchronise with the server stopping, call {@link #join}.  
+     */
+    public FusekiServer start() { 
+        try { server.start(); }
+        catch (Exception e) { throw new FusekiException(e) ; }
+        if ( port == 0 )
+            port = ((ServerConnector)server.getConnectors()[0]).getLocalPort() ;
+        Fuseki.serverLog.info("Start Fuseki (port="+port+")");
+        return this ;
+    }
+
+    /** Stop the server. */
+    public void stop() { 
+        Fuseki.serverLog.info("Stop Fuseki (port="+port+")");
+        try { server.stop(); }
+        catch (Exception e) { throw new FusekiException(e) ; }
+    }
+    
+    /** Wait for the server to exit. This call is blocking. */
+    public void join() {
+        try { server.join(); }
+        catch (Exception e) { throw new FusekiException(e) ; }
+    }
+    
+    /** FusekiServer.Builder */
+    public static class Builder {
+        private Map<String, DataService> map                = new HashMap<>() ;
+        // Default values.
+        private int                      port               = 3330 ;
+        private boolean                  loopback           = false ;
+        private boolean                  withStats          = false ;
+        // Other servlets to add.
+        private List<Pair<String, HttpServlet>> other = new ArrayList<>();
+        private String                   contextPath        = "/" ;
+        private String                   staticContentDir   = null ;
+        private SecurityHandler          securityHandler    = null ;
+
+        /** Set the port to run on. */ 
+        public Builder setPort(int port) {
+            if ( port < 0 )
+                throw new IllegalArgumentException("Illegal port="+port+" : Port must be greater than or equal to zero.") ;
+            this.port = port ;
+            return this ;
+        }
+        
+        /** Context path to Fuseki.  If it's "/" then Fuseki URL look like
+         * "http://host:port/dataset/query" else "http://host:port/path/dataset/query" 
+         */
+        public Builder setContextPath(String path) {
+            this.contextPath = path ;
+            return this ;
+        }
+        
+        /** Restrict the server to only responding to the localhost interface. */ 
+        public Builder setLoopback(boolean loopback) {
+            this.loopback = loopback;
+            return this ;
+        }
+
+        /** Set the location (filing system directory) to serve static file from. */ 
+        public Builder setStaticFileBase(String directory) {
+            this.staticContentDir = directory;
+            return this ;
+        }
+        
+        /** Set a Jetty SecurityHandler.
+         *  By default, the server runs with no security.
+         *  This is more for using the basic server for testing.
+         *  The full Fuseki server provides secjurity with Apache Shiro
+         *  and a defensive reverse proxy (e.g. Apache httpd) in front og the Jetty server
+         *  can also be used, which provides a wide varient of proven security options.   
+         */
+        public Builder setSecurityHandler(SecurityHandler securityHandler) {
+            this.securityHandler = securityHandler;
+            return this;
+        }
+
+        /** Add the "/$/stats" servlet that responds with stats about the server,
+         * including counts of all calls made.
+         */ 
+        public Builder enableStats(boolean withStats) {
+            this.withStats = withStats;
+            return this ;
+        }
+
+        /** Add the dataset with given name and a default set of services including update */  
+        public Builder add(String name, Dataset ds) {
+            return add(name, ds.asDatasetGraph()) ;
+        }
+
+        /** Add the dataset with given name and a default set of services including update */  
+        public Builder add(String name, DatasetGraph dsg) {
+            return add(name, dsg, true) ;
+        }
+
+        /** Add the dataset with given name and a default set of services. */  
+        public Builder add(String name, Dataset ds, boolean allowUpdate) {
+            return add(name, ds.asDatasetGraph(), allowUpdate) ;
+        }
+        
+        /** Add the dataset with given name and a default set of services. */  
+        public Builder add(String name, DatasetGraph dsg, boolean allowUpdate) {
+            DataService dSrv = FusekiBuilder.buildDataService(dsg, allowUpdate) ; 
+            return add(name, dSrv) ;
+        }
+        
+        /** Add a data service that includes dataset and service names.
+         * A {@link DataService} allows for choices of the various endpoint names.
+         */  
+        public Builder add(String name, DataService dataService) {
+            return add$(name, dataService) ; 
+        }
+        
+        private Builder add$(String name, DataService dataService) {
+            name = DataAccessPoint.canonical(name) ;
+            if ( map.containsKey(name) )
+                throw new FusekiConfigException("Data service name already registered: "+name) ;
+            map.put(name, dataService) ;
+            return this ;
+        }
+
+        /** Read and parse a Fuseki services/datasets file.
+         *  <p>
+         *  The application is responsible for ensuring a correct classpath. For example,
+         *  including a dependency on {@code jena-text} if the configuration file
+         *  includes a text index.     
+         */
+        public Builder parseConfigFile(String filename) {
+            List<DataAccessPoint> x = FusekiConfig.readConfigurationFile(filename) ;
+            // Unbundle so that they accumulate.
+            x.forEach(dap-> add(dap.getName(), dap.getDataService())) ;
+            return this ;
+        }
+
+        /**
+         * Add the given servlet with the pathSpec. These are added so that they are
+         * checked after the Fuseki filter for datasets and before the static content
+         * handler (which is the last servlet) used for {@link #setStaticFileBase(String)}.
+         */
+        public Builder addServlet(String pathSpec, HttpServlet servlet) {
+            other.add(Pair.create(pathSpec, servlet));
+            return this;
+        }
+        
+        /** Build a server according to the current description */ 
+        public FusekiServer build() {
+            DataAccessPointRegistry registry = new DataAccessPointRegistry() ;
+            map.forEach((name, dSrv) -> {
+                DataAccessPoint dap = new DataAccessPoint(name, dSrv) ;
+                registry.put(name, dap) ;
+            }) ;
+            ServletContextHandler handler = buildServletContext(contextPath, registry) ;
+            
+            setMimeTypes(handler);
+            servlets(handler);
+            
+            DataAccessPointRegistry.set(handler.getServletContext(), registry) ;
+            Server server = jettyServer(port, loopback) ;
+            server.setHandler(handler);
+            return new FusekiServer(port, server) ;
+        }
+
+        /** Build a ServletContextHandler with the Fuseki router : {@link FusekiFilter} */
+        private ServletContextHandler buildServletContext(String contextPath, DataAccessPointRegistry registry) {
+            if ( contextPath == null || contextPath.isEmpty() )
+                contextPath = "/" ;
+            else if ( !contextPath.startsWith("/") )
+                contextPath = "/" + contextPath ;
+            ServletContextHandler context = new ServletContextHandler() ;
+            context.setDisplayName(Fuseki.servletRequestLogName) ;
+            context.setErrorHandler(new FusekiErrorHandler1()) ;
+            context.setContextPath(contextPath) ;
+            if ( securityHandler != null )
+                context.setSecurityHandler(securityHandler);
+            
+            return context ;
+        }
+        
+        private static void setMimeTypes(ServletContextHandler context) {
+            MimeTypes mimeTypes = new MimeTypes();
+            // RDF syntax
+            mimeTypes.addMimeMapping("nt",      WebContent.contentTypeNTriples);
+            mimeTypes.addMimeMapping("nq",      WebContent.contentTypeNQuads);
+            mimeTypes.addMimeMapping("ttl",     WebContent.contentTypeTurtle+";charset=utf-8");
+            mimeTypes.addMimeMapping("trig",    WebContent.contentTypeTriG+";charset=utf-8");
+            mimeTypes.addMimeMapping("rdfxml",  WebContent.contentTypeRDFXML);
+            mimeTypes.addMimeMapping("jsonld",  WebContent.contentTypeJSONLD);
+            mimeTypes.addMimeMapping("rj",      WebContent.contentTypeRDFJSON);
+            mimeTypes.addMimeMapping("rt",      WebContent.contentTypeRDFThrift);
+            mimeTypes.addMimeMapping("trdf",    WebContent.contentTypeRDFThrift);
+
+            // SPARQL syntax
+            mimeTypes.addMimeMapping("rq",      WebContent.contentTypeSPARQLQuery);
+            mimeTypes.addMimeMapping("ru",      WebContent.contentTypeSPARQLUpdate);
+
+            // SPARQL Result set
+            mimeTypes.addMimeMapping("rsj",     WebContent.contentTypeResultsJSON);
+            mimeTypes.addMimeMapping("rsx",     WebContent.contentTypeResultsXML);
+            mimeTypes.addMimeMapping("srt",     WebContent.contentTypeResultsThrift);
+
+            // Other
+            mimeTypes.addMimeMapping("txt",     WebContent.contentTypeTextPlain);
+            mimeTypes.addMimeMapping("csv",     WebContent.contentTypeTextCSV);
+            mimeTypes.addMimeMapping("tsv",     WebContent.contentTypeTextTSV);
+            context.setMimeTypes(mimeTypes);
+        }
+
+        private void servlets(ServletContextHandler context) {
+            // Fuseki dataset services filter
+            FusekiFilter ff = new FusekiFilter() ;
+            FilterHolder h = new FilterHolder(ff) ;
+            context.addFilter(h, "/*", null) ;
+
+            other.forEach(p->addServlet(context, p.getLeft(), p.getRight()));
+            
+            if ( withStats )
+                addServlet(context, "/$/stats", new ActionStats()) ;
+            
+            if ( staticContentDir != null ) {
+                DefaultServlet staticServlet = new DefaultServlet() ;
+                ServletHolder staticContent = new ServletHolder(staticServlet) ;
+                staticContent.setInitParameter("resourceBase", staticContentDir) ;
+                context.addServlet(staticContent, "/");
+            }
+                
+        }
+
+        private static void addServlet(ServletContextHandler context, String pathspec, HttpServlet httpServlet) {
+            ServletHolder sh = new ServletHolder(httpServlet);
+            context.addServlet(sh, pathspec) ;
+        }
+
+        /** Jetty server */
+        private static Server jettyServer(int port, boolean loopback) {
+            Server server = new Server() ;
+            HttpConnectionFactory f1 = new HttpConnectionFactory() ;
+            // Some people do try very large operations ... really, should use POST.
+            f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
+            f1.getHttpConfiguration().setOutputBufferSize(1024 * 1024) ;
+            // Do not add "Server: Jetty(....) when not a development system.
+            if ( ! Fuseki.outputJettyServerHeader )
+                f1.getHttpConfiguration().setSendServerVersion(false) ;
+            ServerConnector connector = new ServerConnector(server, f1) ;
+            connector.setPort(port) ;
+            server.addConnector(connector);
+            if ( loopback )
+                connector.setHost("localhost");
+            return server ;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestAuth.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestAuth.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestAuth.java
index 8b10f50..fc0eccb 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestAuth.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestAuth.java
@@ -98,7 +98,7 @@ public class FusekiTestAuth {
     public static final String serviceQuery()       { return "http://localhost:"+port()+datasetPath()+"/query" ; }
     public static final String serviceGSP()         { return "http://localhost:"+port()+datasetPath()+"/data" ; }
     
-    private static FusekiEmbeddedServer server ;
+    private static FusekiServer server ;
 
     /** Setup a testing server, using the given  Jetty {@link SecurityHandler} for authentication. 
      * The server will have an empty, in-emory transactional dataset.
@@ -111,7 +111,7 @@ public class FusekiTestAuth {
      */
     public static void setupServer(boolean updateable, SecurityHandler sh, DatasetGraph dsg) {
         dsgTesting = dsg;
-        server = FusekiEmbeddedServer.create()
+        server = FusekiServer.create()
             .add(datasetPath(), dsgTesting)
             .setPort(port())
             .setSecurityHandler(sh)

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestServer.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestServer.java
index 72deb5d..b661e5d 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestServer.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/FusekiTestServer.java
@@ -77,12 +77,12 @@ import org.apache.jena.update.UpdateProcessor ;
  * Much of this machinery is unnessecary for just running a sever in the background:
  * 
  * <pre>
- *   private static FusekiEmbeddedServer server ;
+ *   private static FusekiServer server ;
  *   private static DatasetGraph serverdsg = DatasetGraphFactory.createTxnMem() ;
  *
  *   &#64;BeforeClass
  *   public static void beforeClass() {
- *       server = FusekiEmbeddedServer.create()
+ *       server = FusekiServer.create()
  *           .setPort(....)
  *           .add("/ds", serverdsg)
  *           .build()
@@ -215,7 +215,7 @@ public class FusekiTestServer {
     
     // reference count of start/stop server
     private static AtomicInteger countServer = new AtomicInteger() ; 
-    private static FusekiEmbeddedServer server        = null ;
+    private static FusekiServer server        = null ;
     
     /*package*/ static void allocServer() {
         if ( countServer.getAndIncrement() == 0 )
@@ -229,7 +229,7 @@ public class FusekiTestServer {
     
     /*package*/ static void setupServer(boolean updateable) {
         dsgTesting = DatasetGraphFactory.createTxnMem();
-        server = FusekiEmbeddedServer.create()
+        server = FusekiServer.create()
             .add(datasetPath(), dsgTesting)
             .setPort(port())
             .build()

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestEmbeddedFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestEmbeddedFuseki.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestEmbeddedFuseki.java
index 2743bcb..1925753 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestEmbeddedFuseki.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestEmbeddedFuseki.java
@@ -66,7 +66,7 @@ public class TestEmbeddedFuseki {
     @Test public void embedded_01() {
         DatasetGraph dsg = dataset() ;
         int port = 3330 ;   // Default port.
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create().add("/ds", dsg).build() ;
+        FusekiServer server = FusekiServer.create().add("/ds", dsg).build() ;
         assertTrue(server.getDataAccessPointRegistry().isRegistered("/ds")) ;
         server.start() ;
         query("http://localhost:"+port+"/ds/query", "SELECT * { ?s ?p ?o}", qExec-> {
@@ -80,7 +80,7 @@ public class TestEmbeddedFuseki {
     @Test public void embedded_02() {
         DatasetGraph dsg = dataset() ;
         int port = 0 ;//FusekiEnv.choosePort() ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.make(port, "/ds2", dsg) ;
+        FusekiServer server = FusekiServer.make(port, "/ds2", dsg) ;
         DataAccessPointRegistry registry = server.getDataAccessPointRegistry() ;
         // But no /ds
         assertEquals(1, registry.size()) ;
@@ -95,7 +95,7 @@ public class TestEmbeddedFuseki {
     @Test public void embedded_03() {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .add("/ds1", dsg) 
             .build() ;
@@ -130,7 +130,7 @@ public class TestEmbeddedFuseki {
         dataService.addEndpoint(OperationName.Update, "");
         int port = FusekiLib.choosePort() ;
         
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .add("/data", dataService)
             .build() ;
@@ -169,7 +169,7 @@ public class TestEmbeddedFuseki {
     @Test public void embedded_05() {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .add("/ds0", dsg) 
             .build() ;
@@ -184,7 +184,7 @@ public class TestEmbeddedFuseki {
     @Test public void embedded_06() {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .add("/ds0", dsg)
             .enableStats(true)
@@ -201,7 +201,7 @@ public class TestEmbeddedFuseki {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
         
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .setContextPath("/ABC")
             .add("/ds", dsg) 
@@ -219,7 +219,7 @@ public class TestEmbeddedFuseki {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
 
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .parseConfigFile(DIR+"config.ttl") 
             .build() ;
@@ -233,7 +233,7 @@ public class TestEmbeddedFuseki {
         DatasetGraph dsg = dataset() ;
         int port = FusekiLib.choosePort() ;
 
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .setPort(port)
             .setContextPath("/ABC")
             .parseConfigFile(DIR+"config.ttl") 
@@ -257,7 +257,7 @@ public class TestEmbeddedFuseki {
         DataService dSrv = new DataService(dsg) ;
         dSrv.addEndpoint(OperationName.Query, "q") ;
         dSrv.addEndpoint(OperationName.GSP_R, "gsp") ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .add("/dsrv1", dSrv)
             .setPort(port)
             .build() ;
@@ -276,7 +276,7 @@ public class TestEmbeddedFuseki {
         DataService dSrv = new DataService(dsg) ;
         dSrv.addEndpoint(OperationName.Query, "q") ;
         dSrv.addEndpoint(OperationName.GSP_R, "gsp") ;
-        FusekiEmbeddedServer server = FusekiEmbeddedServer.create()
+        FusekiServer server = FusekiServer.create()
             .add("/dsrv1", dSrv)
             .setStaticFileBase(DIR)
             .setPort(port)

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
index bb45b8f..7a154c2 100644
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
+++ b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
@@ -53,9 +53,9 @@ public class TestMultipleEmbedded {
         DatasetGraph dsg = dataset() ;
 
         int port = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server1 = FusekiEmbeddedServer.create().setPort(port).add("/ds1", dsg).build() ;
+        FusekiServer server1 = FusekiServer.create().setPort(port).add("/ds1", dsg).build() ;
         // Same port - Bbad.
-        FusekiEmbeddedServer server2 = FusekiEmbeddedServer.create().setPort(port).add("/ds2", dsg).build() ;
+        FusekiServer server2 = FusekiServer.create().setPort(port).add("/ds2", dsg).build() ;
     
         server1.start();
         
@@ -75,11 +75,11 @@ public class TestMultipleEmbedded {
     public void multiple_02() {
         DatasetGraph dsg = dataset() ;
         int port1 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server1 = FusekiEmbeddedServer.create().setPort(port1).add("/ds1", dsg).build() ;
+        FusekiServer server1 = FusekiServer.create().setPort(port1).add("/ds1", dsg).build() ;
 
         // Different port - good
         int port2 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server2 = FusekiEmbeddedServer.create().setPort(port2).add("/ds2", dsg).build() ;
+        FusekiServer server2 = FusekiServer.create().setPort(port2).add("/ds2", dsg).build() ;
 
         try {
             server1.start();
@@ -97,11 +97,11 @@ public class TestMultipleEmbedded {
         DatasetGraph dsg2 = dataset() ;
         // Same name.
         int port1 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server1 = FusekiEmbeddedServer.create().setPort(port1).add("/ds", dsg1).build().start() ;
+        FusekiServer server1 = FusekiServer.create().setPort(port1).add("/ds", dsg1).build().start() ;
         Txn.executeWrite(dsg1, ()->dsg1.add(q1));
         
         int port2 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server2 = FusekiEmbeddedServer.create().setPort(port2).add("/ds", dsg2).build().start() ;
+        FusekiServer server2 = FusekiServer.create().setPort(port2).add("/ds", dsg2).build().start() ;
         Txn.executeWrite(dsg2, ()->dsg2.add(q2));
         
         query("http://localhost:"+port1+"/ds/", "SELECT * {?s ?p 1}", qExec->{
@@ -130,11 +130,11 @@ public class TestMultipleEmbedded {
         DatasetGraph dsg = dataset() ;
         
         int port1 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server1 = FusekiEmbeddedServer.create().setPort(port1).add("/ds1", dsg).build().start() ;
+        FusekiServer server1 = FusekiServer.create().setPort(port1).add("/ds1", dsg).build().start() ;
         Txn.executeWrite(dsg, ()->dsg.add(q1));
         
         int port2 = FusekiLib.choosePort() ;
-        FusekiEmbeddedServer server2 = FusekiEmbeddedServer.create().setPort(port2).add("/ds2", dsg).build().start() ;
+        FusekiServer server2 = FusekiServer.create().setPort(port2).add("/ds2", dsg).build().start() ;
         Txn.executeWrite(dsg, ()->dsg.add(q2));
         
         query("http://localhost:"+port1+"/ds1", "SELECT * {?s ?p ?o}", qExec->{

http://git-wip-us.apache.org/repos/asf/jena/blob/2e579e38/jena-integration-tests/src/test/java/org/apache/jena/test/rdfconnection/TestRDFConnectionRemote.java
----------------------------------------------------------------------
diff --git a/jena-integration-tests/src/test/java/org/apache/jena/test/rdfconnection/TestRDFConnectionRemote.java b/jena-integration-tests/src/test/java/org/apache/jena/test/rdfconnection/TestRDFConnectionRemote.java
index b60d0b9..4b2615f 100644
--- a/jena-integration-tests/src/test/java/org/apache/jena/test/rdfconnection/TestRDFConnectionRemote.java
+++ b/jena-integration-tests/src/test/java/org/apache/jena/test/rdfconnection/TestRDFConnectionRemote.java
@@ -20,7 +20,7 @@ package org.apache.jena.test.rdfconnection;
 
 import org.apache.jena.atlas.logging.LogCtl ;
 import org.apache.jena.fuseki.Fuseki ;
-import org.apache.jena.fuseki.embedded.FusekiEmbeddedServer ;
+import org.apache.jena.fuseki.embedded.FusekiServer ;
 import org.apache.jena.rdfconnection.AbstractTestRDFConnection;
 import org.apache.jena.rdfconnection.RDFConnection;
 import org.apache.jena.rdfconnection.RDFConnectionFactory;
@@ -32,12 +32,12 @@ import org.junit.Before ;
 import org.junit.BeforeClass ;
 
 public class TestRDFConnectionRemote extends AbstractTestRDFConnection {
-    private static FusekiEmbeddedServer server ;
+    private static FusekiServer server ;
     private static DatasetGraph serverdsg = DatasetGraphFactory.createTxnMem() ;
     
     @BeforeClass
     public static void beforeClass() {
-        server = FusekiEmbeddedServer.create()
+        server = FusekiServer.create()
             .setPort(2244)
             .add("/ds", serverdsg)
             .build() ;


[3/3] jena git commit: JENA-1371: Merge commit 'refs/pull/268/head' of github.com:apache/jena

Posted by an...@apache.org.
JENA-1371: Merge commit 'refs/pull/268/head' of github.com:apache/jena


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/f30ac0f8
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/f30ac0f8
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/f30ac0f8

Branch: refs/heads/master
Commit: f30ac0f89d7657a5cd2a65b4f6a11b18b58c9cd4
Parents: 6857bf5 2e579e3
Author: Andy Seaborne <an...@apache.org>
Authored: Fri Jul 7 16:29:33 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri Jul 7 16:29:33 2017 +0100

----------------------------------------------------------------------
 .../apache/jena/fuseki/cmds/FusekiBasicCmd.java |  10 +-
 .../apache/jena/fuseki/build/FusekiConfig.java  |   6 +-
 .../org/apache/jena/fuseki/cmd/FusekiCmd.java   |   4 +-
 .../jena/fuseki/mgt/ActionBackupList.java       |   8 +-
 .../apache/jena/fuseki/mgt/ActionDatasets.java  |  12 +-
 .../java/org/apache/jena/fuseki/mgt/Backup.java |   4 +-
 .../apache/jena/fuseki/server/FusekiEnv.java    |  55 +--
 .../apache/jena/fuseki/server/FusekiServer.java | 420 -----------------
 .../fuseki/server/FusekiServerListener.java     |  10 +-
 .../apache/jena/fuseki/server/FusekiSystem.java | 463 +++++++++++++++++++
 .../fuseki/server/ShiroEnvironmentLoader.java   |   2 +-
 .../apache/jena/fuseki/server/SystemState.java  |   2 +-
 .../java/org/apache/jena/fuseki/ServerCtl.java  |   2 +-
 .../fuseki/embedded/FusekiEmbeddedServer.java   | 333 +------------
 .../jena/fuseki/embedded/FusekiServer.java      | 390 ++++++++++++++++
 .../jena/fuseki/embedded/FusekiTestAuth.java    |   4 +-
 .../jena/fuseki/embedded/FusekiTestServer.java  |   8 +-
 .../fuseki/embedded/TestEmbeddedFuseki.java     |  22 +-
 .../fuseki/embedded/TestMultipleEmbedded.java   |  16 +-
 .../rdfconnection/TestRDFConnectionRemote.java  |   6 +-
 20 files changed, 932 insertions(+), 845 deletions(-)
----------------------------------------------------------------------