| /* |
| * 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.riot.adapters; |
| |
| import java.io.*; |
| import java.util.Iterator ; |
| |
| import org.apache.jena.atlas.io.IO; |
| import org.apache.jena.atlas.logging.FmtLog; |
| import org.apache.jena.atlas.web.TypedInputStream ; |
| import org.apache.jena.rdf.model.Model ; |
| import org.apache.jena.rdf.model.ModelFactory; |
| import org.apache.jena.riot.Lang ; |
| import org.apache.jena.riot.RDFDataMgr ; |
| import org.apache.jena.riot.RDFLanguages ; |
| import org.apache.jena.riot.SysRIOT ; |
| import org.apache.jena.riot.system.stream.* ; |
| import org.apache.jena.shared.JenaException; |
| import org.apache.jena.shared.NotFoundException; |
| import org.apache.jena.shared.WrappedIOException; |
| import org.apache.jena.util.FileManager ; |
| import org.apache.jena.util.FileUtils ; |
| import org.apache.jena.util.TypedStream ; |
| 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> |
| * </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 StreamManager |
| * @see LocationMapper |
| * @see FileUtils |
| */ |
| |
| public class AdapterFileManager implements org.apache.jena.util.FileManager |
| { |
| // This is a legacy class - it provides FileManager calls onto the RIOT equivalents. |
| // The different aspects are now split out |
| // and this class maintains the old interface. |
| // Aspects: StreamManager, LocationMapper, Model cache. |
| // and this class exists to maintain the old interfaces and the |
| // combination of stream and model reading. |
| |
| // RIOT reader uses StreamManager. |
| // Each FileManager has a StreamManager. |
| |
| /** Delimiter between path entries : because URI scheme names use : we only allow ; */ |
| //public static final String PATH_DELIMITER = ";"; |
| //public static final String filePathSeparator = java.io.File.separator ; |
| |
| private static Logger log = LoggerFactory.getLogger(AdapterFileManager.class) ; |
| |
| private static AdapterFileManager instance = null ; |
| private final StreamManager streamManager ; |
| |
| // -------- Cache operations |
| // See also loadModelWorker which uses the cache. |
| // These are in the FileManager for legacy reasons. |
| private FileManagerModelCache modelCache = new FileManagerModelCache() ; |
| |
| /** |
| * Get the global file manager. |
| * |
| * @return the global file manager |
| */ |
| public static AdapterFileManager get() { |
| if ( instance == null ) |
| instance = makeGlobal() ; |
| return instance ; |
| } |
| |
| /** |
| * 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(AdapterFileManager globalFileManager) { |
| instance = globalFileManager ; |
| } |
| |
| /** Create an uninitialized StreamManager */ |
| private AdapterFileManager() { |
| streamManager = new StreamManager() ; |
| } |
| |
| @Override |
| public FileManager clone() { |
| StreamManager sm = streamManager.clone() ; |
| AdapterFileManager x = new AdapterFileManager(sm) ; |
| return x ; |
| } |
| |
| public AdapterFileManager(StreamManager streamManager) { |
| this(streamManager, streamManager == null ? null : streamManager.getLocationMapper()) ; |
| } |
| |
| /** Create a FileManger using a RIOT StreamManager and RIOT LocationMapper */ |
| public AdapterFileManager(StreamManager streamManager, LocationMapper mapper) { |
| if ( streamManager == null ) |
| streamManager = new StreamManager() ; |
| this.streamManager = streamManager ; |
| streamManager.setLocationMapper(mapper) ; |
| } |
| |
| /** Create a "standard" FileManager. */ |
| public static AdapterFileManager makeGlobal() { |
| AdapterFileManager fMgr = new AdapterFileManager(StreamManager.get()) ; |
| return fMgr ; |
| } |
| |
| /** Return the associate stream manager */ |
| public StreamManager getStreamManager() { |
| return streamManager ; |
| } |
| |
| /** Set the location mapping */ |
| @Override |
| public void setLocationMapper(org.apache.jena.util.LocationMapper mapper) { |
| streamManager.setLocationMapper(AdapterLib.copyConvert(mapper)) ; |
| } |
| |
| /** Get the location mapping */ |
| @Override |
| public org.apache.jena.util.LocationMapper getLocationMapper() { |
| return new AdapterLocationMapper(streamManager.getLocationMapper()) ; |
| } |
| |
| /** Return an iterator over all the handlers */ |
| @Override |
| public Iterator<org.apache.jena.util.Locator> locators() { |
| throw new UnsupportedOperationException() ; |
| } |
| |
| /** Remove a locator */ |
| @Override |
| public void remove(org.apache.jena.util.Locator loc) { |
| throw new UnsupportedOperationException() ; |
| } |
| |
| /** Add a locator to the end of the locators list */ |
| @Override |
| public void addLocator(org.apache.jena.util.Locator oldloc) { |
| Locator loc = AdapterLib.convert(oldloc) ; |
| log.debug("Add location: " + loc.getName()) ; |
| streamManager.addLocator(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) ; |
| streamManager.addLocator(fLoc) ; |
| } |
| |
| /** Add a class loader locator */ |
| @Override |
| public void addLocatorClassLoader(ClassLoader cLoad) { |
| LocatorClassLoader cLoc = new LocatorClassLoader(cLoad) ; |
| streamManager.addLocator(cLoc) ; |
| } |
| |
| @Override |
| public void addLocatorURL() { |
| addLocatorHTTP(); |
| } |
| |
| public void addLocatorHTTP() { |
| Locator loc = new LocatorHTTP() ; |
| streamManager.addLocator(loc) ; |
| } |
| |
| public void addLocatorFTP() { |
| Locator loc = new LocatorFTP() ; |
| streamManager.addLocator(loc) ; |
| } |
| |
| |
| /** Add a zip file locator */ |
| @Override |
| public void addLocatorZip(String zfn) { |
| Locator loc = new LocatorZip(zfn) ; |
| streamManager.addLocator(loc) ; |
| } |
| |
| // -------- Cache operations (start) |
| /** Reset the model cache */ |
| @Override |
| public void resetCache() { |
| modelCache.resetCache() ; |
| } |
| |
| /** Change the state of model cache : does not clear the cache */ |
| @Override |
| public void setModelCaching(boolean state) { |
| modelCache.setModelCaching(state) ; |
| } |
| |
| /** return whether caching is on of off */ |
| @Override |
| public boolean isCachingModels() { |
| return modelCache.isCachingModels() ; |
| } |
| |
| /** Read out of the cache - return null if not in the cache */ |
| @Override |
| public Model getFromCache(String filenameOrURI) { |
| return modelCache.getFromCache(filenameOrURI) ; |
| } |
| |
| @Override |
| public boolean hasCachedModel(String filenameOrURI) { |
| return modelCache.hasCachedModel(filenameOrURI) ; |
| } |
| |
| @Override |
| public void addCacheModel(String uri, Model m) { |
| modelCache.addCacheModel(uri, m) ; |
| } |
| |
| @Override |
| public void removeCacheModel(String uri) { |
| modelCache.removeCacheModel(uri) ; |
| } |
| |
| // -------- Cache operations (end) |
| |
| 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) ; |
| |
| Lang lang = |
| (syntax != null) |
| ? RDFLanguages.nameToLang(syntax) |
| : RDFLanguages.resourceNameToLang(mappedURI, Lang.RDFXML) ; |
| |
| // Not : RDFDataMgr.read(model, mappedURI, baseURI, lang); |
| // Allow model.read to be overridden e.g. by OntModel which does import processing. |
| if ( baseURI == null ) |
| baseURI = SysRIOT.chooseBaseIRI(filenameOrURI) ; |
| try(TypedInputStream in = streamManager.openNoMapOrNull(mappedURI)) { |
| if ( in == null ) |
| { |
| FmtLog.debug(log, "Failed to locate '%s'", mappedURI); |
| throw new NotFoundException("Not found: "+filenameOrURI) ; |
| } |
| Lang lang2 = RDFDataMgr.determineLang(mappedURI, in.getContentType(), lang); |
| // May be overridden by model implementation. |
| model.read(in, baseURI, lang2.getName()) ; |
| } |
| return model ; |
| } |
| |
| /** |
| * Open a file using the locators of this FileManager Throws |
| * RiotNotFoundException if not found. |
| */ |
| @Override |
| public InputStream open(String filenameOrURI) { |
| return streamManager.open(filenameOrURI) ; |
| } |
| |
| /** Apply the mapping of a filename or URI */ |
| @Override |
| public String mapURI(String filenameOrURI) { |
| return streamManager.mapURI(filenameOrURI) ; |
| } |
| |
| /** |
| * Open a file using the locators of this FileManager but without location |
| * mapping. Throws RiotNotFoundException if not found. |
| */ |
| @Override |
| public InputStream openNoMap(String filenameOrURI) { |
| return streamManager.openNoMap(filenameOrURI) ; |
| } |
| |
| /** |
| * Open a file using the locators of this FileManager without location |
| * mapping. Return null if not found |
| */ |
| @Override |
| public TypedStream openNoMapOrNull(String filenameOrURI) { |
| return AdapterLib.convert(streamManager.openNoMapOrNull(filenameOrURI)) ; |
| } |
| |
| // -------- Cache operations (end) |
| |
| // LEGACY |
| |
| @Override |
| public Model loadModelInternal(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. |
| */ |
| @Deprecated |
| @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. |
| */ |
| @Deprecated |
| @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 ; |
| } |
| |
| @Override |
| public Model readModelInternal(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. |
| */ |
| @Deprecated |
| @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. |
| */ |
| @Deprecated |
| @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. |
| String tmp = baseURI.substring("file:".length()) ; |
| File f = new File(tmp) ; |
| baseURI = "file:///"+f.getCanonicalPath() ; |
| baseURI = baseURI.replace('\\','/') ; |
| |
| // baseURI = baseURI.replace(" ","%20"); |
| // baseURI = baseURI.replace("~","%7E"); |
| // Convert to URI. Except that it removes /// |
| // Could do that and fix up (again) |
| //java.net.URL u = new java.net.URL(baseURI) ; |
| //baseURI = u.toExternalForm() ; |
| } catch (Exception ex) {} |
| } |
| } |
| return baseURI ; |
| } |
| |
| if ( baseURI.startsWith("/") ) |
| return "file://"+baseURI ; |
| return "file:"+baseURI ; |
| } |
| |
| /** |
| * @deprecated Use {@link IO#readWholeFileAsUTF8(InputStream)} |
| */ |
| @Override |
| @Deprecated |
| public String readWholeFileAsUTF8(InputStream in) |
| { |
| try { |
| return IO.readWholeFileAsUTF8(in); |
| } catch (IOException ex) |
| { throw new WrappedIOException(ex) ; } |
| } |
| |
| /** |
| * @deprecated Use {@link IO#readWholeFileAsUTF8(String)} |
| */ |
| @Override |
| public String readWholeFileAsUTF8(String filename) |
| { |
| InputStream in = open(filename) ; |
| if ( in == null ) |
| throw new NotFoundException("File not found: "+filename) ; |
| return readWholeFileAsUTF8(in) ; |
| } |
| } |