You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@jena.apache.org by GitBox <gi...@apache.org> on 2020/06/16 05:58:05 UTC

[GitHub] [jena] kinow commented on a change in pull request #759: JENA-1917: FileManager as interface; Deprecate FileManager.get()

kinow commented on a change in pull request #759:
URL: https://github.com/apache/jena/pull/759#discussion_r440596038



##########
File path: jena-core/src/main/java/org/apache/jena/ontology/OntDocumentManager.java
##########
@@ -54,16 +54,14 @@
  * example:
  * </p>
  * <pre>OntDocumentManager dm = OntDocumentManager.getInstance();
- * dm.setFileManager( FileManager.get() );</pre>
- * <p>Note that in Jena 2.3, we have deprecated the capability of the document manager
- * to store a table of known prefixes, and a table mapping document URI's to ontology language
- * types. <strong>The intention is to remove both of these capabilities from
- * Jena 2.4 onwards</strong>. If this change would be problematic, please send email to the
- * <a href="http://groups.yahoo.com/group/jena-dev">Jena support

Review comment:
       Oh, the list used to be on Yahoo! Groups? That was probably a long time ago?

##########
File path: jena-core/src/main/java/org/apache/jena/n3/N3JenaWriter.java
##########
@@ -105,16 +80,20 @@ N3JenaWriterCommon chooseWriter()
     {
         // Choose the writer
         String writerName = JenaRuntime.getSystemProperty(propWriterName) ;
-        if ( writerName == null ||
-             writerName.equals("N3") || writerName.equals(n3WriterPrettyPrinter) )
+        if ( writerName == null )
+            return new N3JenaWriterPP() ;
+        if ( writerName.equals("N3") )
             return new N3JenaWriterPP() ;
         
-        if ( writerName.equalsIgnoreCase(n3WriterPlain) )
-            return new N3JenaWriterCommon() ;
-        
-        if ( writerName.equalsIgnoreCase(n3WriterTriples) ||
-             writerName.equalsIgnoreCase(n3WriterTriplesAlt) )
-            return new N3JenaWriterTriples() ;
+//        if ( writerName.equals(n3WriterPrettyPrinter) )

Review comment:
       I think the only difference now is that `writerName.equals(n3WriterPrettyPrinter)` used to work, and now it won't? But probably no harm I guess?

##########
File path: jena-core/src/main/java/org/apache/jena/util/FileManagerImpl.java
##########
@@ -0,0 +1,566 @@
+/*
+ * 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.util;
+
+import java.io.* ;
+import java.util.* ;
+
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.rdf.model.ModelFactory ;
+import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException ;
+import org.apache.jena.shared.WrappedIOException ;
+import org.apache.jena.sys.JenaSystem ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** FileManager
+ * 
+ * A FileManager provides access to named file-like resources by opening
+ * InputStreams to things in the filing system, by URL (http: and file:) and
+ * found by the classloader.  It can also load RDF data from such a system
+ * resource into an existing model or create a new (Memory-based) model.
+ * There is a global FileManager which provide uniform access to system
+ * resources: applications may also create specialised FileManagers.
+ * 
+ * A FileManager contains a list of location functions to try: the global
+ * FileManger has one {@link LocatorFile}, one {@link LocatorClassLoader} and
+ * one {@link LocatorURL}
+ * 
+ * Main operations:
+ *  * <ul>

Review comment:
       Extra `*`

##########
File path: jena-core/src/main/java/org/apache/jena/util/FileManagerImpl.java
##########
@@ -0,0 +1,566 @@
+/*
+ * 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.util;
+
+import java.io.* ;
+import java.util.* ;
+
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.rdf.model.ModelFactory ;
+import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException ;
+import org.apache.jena.shared.WrappedIOException ;
+import org.apache.jena.sys.JenaSystem ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** FileManager
+ * 
+ * A FileManager provides access to named file-like resources by opening
+ * InputStreams to things in the filing system, by URL (http: and file:) and
+ * found by the classloader.  It can also load RDF data from such a system
+ * resource into an existing model or create a new (Memory-based) model.
+ * There is a global FileManager which provide uniform access to system
+ * resources: applications may also create specialised FileManagers.
+ * 
+ * A FileManager contains a list of location functions to try: the global
+ * FileManger has one {@link LocatorFile}, one {@link LocatorClassLoader} and
+ * one {@link LocatorURL}
+ * 
+ * Main operations:
+ *  * <ul>
+ * <li>loadModel, readModel : URI to model</li>
+ * <li>open, openNoMap : URI to input stream</li>
+ * <li>mapURI : map URI to another by {@link LocationMapper}</li> 
+ * </ul>
+ * 
+ * Utilities:
+ * <ul>
+ * <li>readWholeFileAsUTF8</li>
+ * <li>optional caching of models<li>
+ * </ul>
+ * 
+ * A FileManager works in conjunction with a LocationMapper.
+ * A {@link LocationMapper} is a set of alternative locations for system
+ * resources and a set of alternative prefix locations.  For example, a local
+ * copy of a common RDF dataset may be used whenever the usual URL is used by
+ * the application.
+ *
+ * The {@link LocatorFile} also supports the idea of "current directory".
+ * 
+ * @see LocationMapper
+ * @see FileUtils
+ */
+ 
+public class FileManagerImpl implements FileManager
+{
+    // The case of the FileManager used first.
+    private static Logger log = LoggerFactory.getLogger(FileManager.class) ;
+    
+    /** Delimiter between path entries : because URI scheme names use : we only allow ; */
+
+    static FileManager fmInstance = null ;
+
+    protected List<Locator> fmHandlers = new ArrayList<>() ;
+    protected LocationMapper fmMapper = null ;
+    
+    static { JenaSystem.init(); }
+
+    /** Get the global file manager.
+     * @return the global file manager
+     */
+    public static FileManager get()
+    {
+        // Singleton pattern adopted in case we later have several file managers.
+        if ( fmInstance == null )

Review comment:
       Should this method be made `synchronized`, or should we tell users of this code that it is not thread-safe? (I think it's not, but my Java-fu is getting utterly confused due to writing more JS & Python at $work)

##########
File path: jena-core/src/main/java/org/apache/jena/util/FileManagerImpl.java
##########
@@ -0,0 +1,566 @@
+/*
+ * 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.util;
+
+import java.io.* ;
+import java.util.* ;
+
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.rdf.model.ModelFactory ;
+import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException ;
+import org.apache.jena.shared.WrappedIOException ;
+import org.apache.jena.sys.JenaSystem ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** FileManager
+ * 
+ * A FileManager provides access to named file-like resources by opening
+ * InputStreams to things in the filing system, by URL (http: and file:) and
+ * found by the classloader.  It can also load RDF data from such a system
+ * resource into an existing model or create a new (Memory-based) model.
+ * There is a global FileManager which provide uniform access to system
+ * resources: applications may also create specialised FileManagers.
+ * 
+ * A FileManager contains a list of location functions to try: the global
+ * FileManger has one {@link LocatorFile}, one {@link LocatorClassLoader} and
+ * one {@link LocatorURL}
+ * 
+ * Main operations:
+ *  * <ul>
+ * <li>loadModel, readModel : URI to model</li>
+ * <li>open, openNoMap : URI to input stream</li>
+ * <li>mapURI : map URI to another by {@link LocationMapper}</li> 
+ * </ul>
+ * 
+ * Utilities:
+ * <ul>
+ * <li>readWholeFileAsUTF8</li>
+ * <li>optional caching of models<li>
+ * </ul>
+ * 
+ * A FileManager works in conjunction with a LocationMapper.
+ * A {@link LocationMapper} is a set of alternative locations for system
+ * resources and a set of alternative prefix locations.  For example, a local
+ * copy of a common RDF dataset may be used whenever the usual URL is used by
+ * the application.
+ *
+ * The {@link LocatorFile} also supports the idea of "current directory".
+ * 
+ * @see LocationMapper
+ * @see FileUtils
+ */
+ 
+public class FileManagerImpl implements FileManager
+{
+    // The case of the FileManager used first.
+    private static Logger log = LoggerFactory.getLogger(FileManager.class) ;
+    
+    /** Delimiter between path entries : because URI scheme names use : we only allow ; */
+
+    static FileManager fmInstance = null ;
+
+    protected List<Locator> fmHandlers = new ArrayList<>() ;
+    protected LocationMapper fmMapper = null ;
+    
+    static { JenaSystem.init(); }
+
+    /** Get the global file manager.
+     * @return the global file manager
+     */
+    public static FileManager get()
+    {
+        // Singleton pattern adopted in case we later have several file managers.
+        if ( fmInstance == null )
+            fmInstance = makeGlobal() ;
+        return fmInstance ;
+    }
+    
+    /** Set the global file manager (as returned by get())
+     * If called before any call to get(), then the usual default filemanager is not created 
+     * @param globalFileManager
+     */
+    public static void setGlobalFileManager(FileManager globalFileManager)
+    {
+        fmInstance = globalFileManager ;
+    }
+    
+    /** Create an uninitialized FileManager */
+
+    protected FileManagerImpl() {}
+    
+    protected static FileManager makeStd() {
+        FileManagerImpl fm = new FileManagerImpl();
+        setStdLocators(fm);
+        return fm;
+    }
+    
+    /** Create with the given location mapper */
+    protected FileManagerImpl(LocationMapper _mapper)    { setLocationMapper(_mapper) ; }
+
+    @Override
+    public FileManager clone() { return clone(this) ; } 
+ 
+    // Isolate to help avoid copy errors.
+    private static FileManager clone(FileManagerImpl filemanager) {
+        FileManagerImpl newFm = new FileManagerImpl() ;
+        newFm.fmHandlers.addAll(filemanager.fmHandlers) ;
+        newFm.fmMapper = null ;
+        if ( filemanager.getLocationMapper() != null )
+            newFm.fmMapper = new LocationMapper(filemanager.getLocationMapper()) ;
+        newFm.cacheModelLoads = false ;
+        newFm.modelCache = null ;
+        return newFm ;
+    }
+
+    /** Create a "standard" FileManager. */
+    public static FileManager makeGlobal()
+    {
+        FileManagerImpl fMgr = new FileManagerImpl(LocationMapper.get()) ;
+        setStdLocators(fMgr) ;
+        return fMgr ;
+    }
+    
+    /** Force a file handler to have the default configuration. */
+    private static void setStdLocators(FileManagerImpl fMgr)
+    {
+        fMgr.fmHandlers.clear() ;
+        fMgr.addLocatorFile() ;
+        fMgr.addLocatorURL() ;
+        fMgr.addLocatorClassLoader(fMgr.getClass().getClassLoader()) ;
+    }
+    /** Set the location mapping */
+    @Override
+    public void setLocationMapper(LocationMapper _mapper) { fmMapper = _mapper ; }
+    
+    /** Get the location mapping */
+    @Override
+    public LocationMapper getLocationMapper() { return fmMapper ; }
+    
+    /** Return an iterator over all the handlers */
+    @Override
+    public Iterator<Locator> locators() { return fmHandlers.listIterator() ; }
+
+    /** Add a locator to the end of the locators list */ 
+    @Override
+    public void addLocator(Locator loc)
+    {
+        log.debug("Add location: "+loc.getName()) ;
+        fmHandlers.add(loc) ; }
+
+    /** Add a file locator */ 
+    @Override
+    public void addLocatorFile() { addLocatorFile(null) ; } 
+
+    /** Add a file locator which uses dir as its working directory */ 
+    @Override
+    public void addLocatorFile(String dir)
+    {
+        LocatorFile fLoc = new LocatorFile(dir) ;
+        addLocator(fLoc) ;
+    }
+    
+    /** Add a class loader locator */ 
+    @Override
+    public void addLocatorClassLoader(ClassLoader cLoad)
+    {
+        LocatorClassLoader cLoc = new LocatorClassLoader(cLoad) ;
+        addLocator(cLoc) ;
+    }
+
+    /** Add a URL locator */
+    @Override
+    public void addLocatorURL()
+    {
+        Locator loc = new LocatorURL() ;
+        addLocator(loc) ;
+    }
+
+    /** Add a zip file locator */
+    @Override
+    public void addLocatorZip(String zfn)
+    {
+        Locator loc = new LocatorZip(zfn) ;
+        addLocator(loc) ;
+    }
+
+    
+    /** Remove a locator */ 
+    @Override
+    public void remove(Locator loc) { fmHandlers.remove(loc) ; }
+
+    // -------- Cache operations
+    boolean cacheModelLoads = false ;
+    Map<String, Model> modelCache = null ;
+    
+    /** Reset the model cache */
+    @Override
+    public void resetCache()
+    {
+        if ( modelCache != null )
+            modelCache.clear() ;
+    }
+    
+    /** Change the state of model cache : does not clear the cache */ 
+    @Override
+    public void setModelCaching(boolean state)
+    {
+        cacheModelLoads = state ;
+        if ( cacheModelLoads && modelCache == null )
+            modelCache = new HashMap<String, Model>() ;
+    }
+
+    /** return whether caching is on of off */
+    @Override
+    public boolean isCachingModels() { return cacheModelLoads ; }
+    
+    /** Read out of the cache - return null if not in the cache */ 
+    @Override
+    public Model getFromCache(String filenameOrURI)
+    { 
+        if ( ! isCachingModels() )
+            return null; 
+        return modelCache.get(filenameOrURI) ;
+    }
+    
+    @Override
+    public boolean hasCachedModel(String filenameOrURI)
+    { 
+        if ( ! isCachingModels() )
+            return false ; 
+        return modelCache.containsKey(filenameOrURI) ;
+    }
+    
+    @Override
+    public void addCacheModel(String uri, Model m)
+    { 
+        if ( isCachingModels() )
+            modelCache.put(uri, m) ;
+    }
+
+    @Override
+    public void removeCacheModel(String uri)
+    { 
+        if ( isCachingModels() )
+            modelCache.remove(uri) ;
+    }
+
+    // -------- Cache operations (end)
+
+    /** Load a model from a file (local or remote).
+     *  This operation may attempt content negotiation for http URLs.
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+     */
+
+    @Override
+    public Model loadModel(String filenameOrURI)
+    { 
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+")") ;
+        
+        return loadModelWorker(filenameOrURI, null, null) ;
+    }
+
+    /** Load a model from a file (local or remote).
+     *  URI is the base for reading the model.
+     * 
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @param rdfSyntax  RDF Serialization syntax. 
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+     */
+
+    @Override
+    public Model loadModel(String filenameOrURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+", "+rdfSyntax+")") ;
+        return loadModelWorker(filenameOrURI, null, rdfSyntax) ;
+    }
+    
+    /** Load a model from a file (local or remote).
+     * 
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @param baseURI  Base URI for loading the RDF model.
+     *  @param rdfSyntax  RDF Serialization syntax. 
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+    */
+
+
+    @Override
+    public Model loadModel(String filenameOrURI, String baseURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+", "+baseURI+", "+rdfSyntax+")") ;
+
+        return loadModelWorker(filenameOrURI, baseURI, rdfSyntax) ;
+    }
+
+    private Model loadModelWorker(String filenameOrURI, String baseURI, String rdfSyntax)
+    {
+        if ( hasCachedModel(filenameOrURI) )
+        {
+            if ( log.isDebugEnabled() )
+                log.debug("Model cache hit: "+filenameOrURI) ;
+            return getFromCache(filenameOrURI) ;
+        }
+
+        Model m = ModelFactory.createDefaultModel() ;
+        readModelWorker(m, filenameOrURI, baseURI, rdfSyntax) ;
+        
+        if ( isCachingModels() )
+            addCacheModel(filenameOrURI, m) ;
+        return m ;
+    }
+    
+    /**
+     * Read a file of RDF into a model.  Guesses the syntax of the file based on filename extension, 
+     *  defaulting to RDF/XML.
+     * @param model
+     * @param filenameOrURI
+     * @return The model or null, if there was an error.
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+")") ;
+        return readModel(model, filenameOrURI, null);
+    }
+    
+    /**
+     * Read a file of RDF into a model.
+     * @param model
+     * @param filenameOrURI
+     * @param rdfSyntax RDF Serialization syntax.
+     * @return The model or null, if there was an error.
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+", "+rdfSyntax+")") ;
+        return readModelWorker(model, filenameOrURI, null, rdfSyntax);
+    }
+
+    /**
+     * Read a file of RDF into a model.
+     * @param model
+     * @param filenameOrURI
+     * @param baseURI
+     * @param syntax
+     * @return The model
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI, String baseURI, String syntax)
+    {
+        
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+", "+baseURI+", "+syntax+")") ;
+        return readModelWorker(model, filenameOrURI, baseURI, syntax) ;
+    }
+    
+    protected Model readModelWorker(Model model, String filenameOrURI, String baseURI, String syntax)
+    {
+        // Doesn't call open() - we want to make the syntax guess based on the mapped URI.
+        String mappedURI = mapURI(filenameOrURI) ;
+
+        if ( log.isDebugEnabled() && ! mappedURI.equals(filenameOrURI) )
+            log.debug("Map: "+filenameOrURI+" => "+mappedURI) ;
+
+        if ( syntax == null && baseURI == null && mappedURI.startsWith( "http:" ) )
+        {
+            syntax = FileUtils.guessLang(mappedURI) ;
+            // Content negotation in next version (FileManager2) 
+            model.read(mappedURI, syntax) ;
+            return model ;
+        }
+        
+        if ( syntax == null )
+        {
+            syntax = FileUtils.guessLang(mappedURI) ;
+            if ( syntax == null || syntax.equals("") )
+                syntax = FileUtils.langXML ;
+            if ( log.isDebugEnabled() ) 
+                log.debug("Syntax guess: "+syntax);
+        }
+
+        if ( baseURI == null )
+            baseURI = chooseBaseURI(filenameOrURI) ;
+
+        TypedStream in = openNoMapOrNull(mappedURI) ;
+        if ( in == null )
+        {
+            FmtLog.debug(log, "Failed to locate '%s'", mappedURI);
+            throw new NotFoundException("Not found: "+filenameOrURI) ;
+        }
+        if ( in.getMimeType() != null )
+        {
+            //syntax
+        }
+        model.read(in.getInput(), baseURI, syntax) ;
+        try { in.getInput().close(); } catch (IOException ex) {}
+        return model ;
+    }
+
+    private static String chooseBaseURI(String baseURI)
+    {
+        String scheme = FileUtils.getScheme(baseURI) ;
+        
+        if ( scheme != null )
+        {
+            if ( scheme.equals("file") )
+            {
+                if ( ! baseURI.startsWith("file:///") )
+                {
+                    try {
+                        // Fix up file URIs.  Yuk.

Review comment:
       :smile: 

##########
File path: jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterFileManager.java
##########
@@ -331,4 +339,189 @@ public InputStream openNoMap(String filenameOrURI) {
     public TypedStream openNoMapOrNull(String filenameOrURI) {
         return AdapterLib.convert(streamManager.openNoMapOrNull(filenameOrURI)) ;
     }
+    
+    // -------- Cache operations (end)
+    
+    // LEGACY 
+
+    /** Load a model from a file (local or remote).
+     *  This operation may attempt content negotiation for http URLs.
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+     */
+
+    @Override
+    public Model loadModel(String filenameOrURI)
+    { 
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+")") ;
+        
+        return loadModelWorker(filenameOrURI, null, null) ;
+    }
+
+    /** Load a model from a file (local or remote).
+     *  URI is the base for reading the model.
+     * 
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @param rdfSyntax  RDF Serialization syntax. 
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+     */
+
+    @Override
+    public Model loadModel(String filenameOrURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+", "+rdfSyntax+")") ;
+        return loadModelWorker(filenameOrURI, null, rdfSyntax) ;
+    }
+    
+    /** Load a model from a file (local or remote).
+     * 
+     *  @param filenameOrURI The filename or a URI (file:, http:)
+     *  @param baseURI  Base URI for loading the RDF model.
+     *  @param rdfSyntax  RDF Serialization syntax. 
+     *  @return a new model
+     *  @exception JenaException if there is syntax error in file.
+    */
+
+
+    @Override
+    public Model loadModel(String filenameOrURI, String baseURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("loadModel("+filenameOrURI+", "+baseURI+", "+rdfSyntax+")") ;
+
+        return loadModelWorker(filenameOrURI, baseURI, rdfSyntax) ;
+    }
+
+    private Model loadModelWorker(String filenameOrURI, String baseURI, String rdfSyntax)
+    {
+        if ( hasCachedModel(filenameOrURI) )
+        {
+            if ( log.isDebugEnabled() )
+                log.debug("Model cache hit: "+filenameOrURI) ;
+            return getFromCache(filenameOrURI) ;
+        }
+
+        Model m = ModelFactory.createDefaultModel() ;
+        readModelWorker(m, filenameOrURI, baseURI, rdfSyntax) ;
+        
+        if ( isCachingModels() )
+            addCacheModel(filenameOrURI, m) ;
+        return m ;
+    }
+    
+    /**
+     * Read a file of RDF into a model.  Guesses the syntax of the file based on filename extension, 
+     *  defaulting to RDF/XML.
+     * @param model
+     * @param filenameOrURI
+     * @return The model or null, if there was an error.
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+")") ;
+        return readModel(model, filenameOrURI, null);
+    }
+    
+    /**
+     * Read a file of RDF into a model.
+     * @param model
+     * @param filenameOrURI
+     * @param rdfSyntax RDF Serialization syntax.
+     * @return The model or null, if there was an error.
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI, String rdfSyntax)
+    {
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+", "+rdfSyntax+")") ;
+        return readModelWorker(model, filenameOrURI, null, rdfSyntax);
+    }
+
+    /**
+     * Read a file of RDF into a model.
+     * @param model
+     * @param filenameOrURI
+     * @param baseURI
+     * @param syntax
+     * @return The model
+     *  @exception JenaException if there is syntax error in file.
+     */    
+
+    @Override
+    public Model readModel(Model model, String filenameOrURI, String baseURI, String syntax)
+    {
+        
+        if ( log.isDebugEnabled() )
+            log.debug("readModel(model,"+filenameOrURI+", "+baseURI+", "+syntax+")") ;
+        return readModelWorker(model, filenameOrURI, baseURI, syntax) ;
+    }
+    
+    private static String chooseBaseURI(String baseURI)
+    {
+        String scheme = FileUtils.getScheme(baseURI) ;
+        
+        if ( scheme != null )
+        {
+            if ( scheme.equals("file") )
+            {
+                if ( ! baseURI.startsWith("file:///") )
+                {
+                    try {
+                        // Fix up file URIs.  Yuk.

Review comment:
       This method looks a lot like another method I'd read on this PR. Could they be merged into one and re-used? Or are they doing something different? (Will have another look after submitting the review)

##########
File path: jena-core/src/main/java/org/apache/jena/util/FileManagerImpl.java
##########
@@ -0,0 +1,566 @@
+/*
+ * 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.util;
+
+import java.io.* ;
+import java.util.* ;
+
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.rdf.model.ModelFactory ;
+import org.apache.jena.shared.JenaException ;
+import org.apache.jena.shared.NotFoundException ;
+import org.apache.jena.shared.WrappedIOException ;
+import org.apache.jena.sys.JenaSystem ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** FileManager
+ * 
+ * A FileManager provides access to named file-like resources by opening
+ * InputStreams to things in the filing system, by URL (http: and file:) and
+ * found by the classloader.  It can also load RDF data from such a system
+ * resource into an existing model or create a new (Memory-based) model.
+ * There is a global FileManager which provide uniform access to system
+ * resources: applications may also create specialised FileManagers.
+ * 
+ * A FileManager contains a list of location functions to try: the global
+ * FileManger has one {@link LocatorFile}, one {@link LocatorClassLoader} and

Review comment:
       s/`FileManger`/`FileManager`




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@jena.apache.org
For additional commands, e-mail: pr-help@jena.apache.org