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 2012/11/18 12:09:30 UTC

svn commit: r1410870 [2/3] - in /jena/trunk/jena-arq/src/main/java/org/apache/jena/riot: ./ adapters/ stream/

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/WebReader2.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/WebReader2.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/WebReader2.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/WebReader2.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,551 @@
+/**
+ * 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;
+
+import java.io.InputStream ;
+import java.io.Reader ;
+import java.io.StringReader ;
+
+import org.apache.jena.riot.stream.StreamManager ;
+import org.openjena.atlas.lib.Sink ;
+import org.openjena.atlas.web.ContentType ;
+import org.openjena.riot.* ;
+import org.openjena.riot.lang.LangRDFXML ;
+import org.openjena.riot.lang.LangRIOT ;
+import org.openjena.riot.lang.SinkQuadsToDataset ;
+import org.openjena.riot.lang.SinkTriplesToGraph ;
+import org.openjena.riot.tokens.Tokenizer ;
+import org.openjena.riot.tokens.TokenizerFactory ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.impl.RDFReaderFImpl ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.sparql.util.Symbol ;
+import com.hp.hpl.jena.sparql.util.Utils ;
+
+/** <p>General purpose reader framework for RDF (triples and quads) syntaxes.</p>   
+ *  <ul>
+ *  <li>HTTP Content negotiation</li>
+ *  <li>File type hint by the extension</li>
+ *  <li>Application language hint</li>
+ *  </ul>
+ * <p>
+ *  It also provide a way to lookup names in different
+ *  locations and to remap URIs to other URIs. 
+ *  </p>
+ *  <p>
+ *  Extensible - a new syntax can be added to the framework. 
+ *  </p>
+ */
+
+public class WebReader2
+{
+    /* Maybe:
+     * static for global (singleton) and locally tailored. 
+     */
+    
+    static Logger log = LoggerFactory.getLogger(WebReader2.class) ;
+    private static String riotBase = "http://jena.apache.org/riot/" ; 
+    private static String streamManagerSymbolStr = riotBase+"streammanager" ; 
+    public static Symbol streamManagerSymbol = Symbol.create(streamManagerSymbolStr) ; 
+
+    public static void wireIntoJena()
+    {
+//        // Wire in generic 
+//        String readerRDF = RDFReaderRIOT.class.getName() ;
+//        RDFReaderFImpl.setBaseReaderClassName("RDF/XML",    readerRDF) ;           // And default
+//        RDFReaderFImpl.setBaseReaderClassName("RDF/XML-ABBREV", readerRDF) ;
+//
+//        RDFReaderFImpl.setBaseReaderClassName("N-TRIPLES",  readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("N-TRIPLE",   readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("N3",         readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("TURTLE",     readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("Turtle",     readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("TTL",        readerRDF) ;
+//        RDFReaderFImpl.setBaseReaderClassName("RDF/JSON",   readerRDF) ;
+        
+      RDFReaderFImpl.setBaseReaderClassName("RDF/XML",    RDFReaderRIOT_RDFXML.class.getName()) ;           // And default
+      RDFReaderFImpl.setBaseReaderClassName("RDF/XML-ABBREV", RDFReaderRIOT_RDFXML.class.getName()) ;
+
+      RDFReaderFImpl.setBaseReaderClassName("N-TRIPLES",  RDFReaderRIOT_NT.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("N-TRIPLE",   RDFReaderRIOT_NT.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("N3",         RDFReaderRIOT_TTL.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("TURTLE",     RDFReaderRIOT_TTL.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("Turtle",     RDFReaderRIOT_TTL.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("TTL",        RDFReaderRIOT_TTL.class.getName()) ;
+      RDFReaderFImpl.setBaseReaderClassName("RDF/JSON",   RDFReaderRIOT_RDFJSON.class.getName()) ;
+    }
+    
+    // Yukky hack to integrate into current jena-core where the structure of model.read assumes
+    // the language is determined before the reading process starts.
+    
+    public static class RDFReaderRIOT_RDFXML extends RDFReaderRIOT   { public RDFReaderRIOT_RDFXML() { super("RDF/XML") ; } }
+    public static class RDFReaderRIOT_TTL extends RDFReaderRIOT      { public RDFReaderRIOT_TTL() { super("TTL") ; } }
+    public static class RDFReaderRIOT_NT extends RDFReaderRIOT       { public RDFReaderRIOT_NT() { super("N-TRIPLE") ; } }
+    public static class RDFReaderRIOT_RDFJSON extends RDFReaderRIOT  { public RDFReaderRIOT_RDFJSON() { super("RDF/JSON") ; } }
+
+    
+    public static void resetJenaReaders()
+    {
+        SysRIOT.resetJenaReaders() ;
+    }
+    
+    /** Read triples into a Model from the given location. 
+     *  The synatx is detemined from input source URI (content negotiation or extension). 
+     * @see #read(Model,String,Lang2,Context) 
+     * @param model Destination for the RDF read.
+     * @param uri   URI to read from (includes file: and a plain file name).
+     */
+    public static void read(Model model, String uri)                    { read(model, uri, null, null, null) ; }
+    
+    /** Read triples into a Model from the given location, with a hint of the language (MIME type) 
+     * @see #read(Model,String,String,Lang2,Context) 
+     * @param model     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Hint for the syntax.
+     */
+    public static void read(Model model, String uri, Lang2 hintLang)   { read(model, uri, hintLang, null) ; }
+    
+    /** Read triples into a Model from the given location, with hint of langauge and the with some parameters for the reader 
+     * @see #read(Model,String,String,Lang2,Context) 
+     * Throws parse errors depending on the language and reader; the Model model may be partially updated.
+     * @param model     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param base      Base URI (defaults to uri).
+     * @param hintLang  Hint for the syntax
+     * @throws RiotNotFoundException if the location is not found - the model is unchanged.
+     */
+    public static void read(Model model, String uri, String base, Lang2 hintLang) { read(model, uri, base, hintLang, null) ; }
+    
+    /** Read triples into a Model from the given location, with some parameters for the reader
+     * @see #read(Model,String,String,Lang2,Context) 
+     * @param model     Destination for the RDF read
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param context   Content object to control reading process.
+     */ 
+    public static void read(Model model, String uri, Context context)   { read(model, uri, null, context) ; }
+    
+    /** Read triples into a Model from the given location, with hint of langauge and the with some parameters for the reader 
+     * @see #read(Model,String,String,Lang2,Context) 
+     * @param model     Destination for the RDF read
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+    */
+    public static void read(Model model, String uri, Lang2 hintLang, Context context)
+    {
+        read(model, uri, uri, hintLang, context) ;
+    }
+    
+    /** Read triples into a Model from the given location, with hint of langauge and the with some parameters for the reader 
+     * Throws parse errors depending on the language and reader; the Model model may be partially updated.
+     * @param model     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param base      Base URI (defaults to uri).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+     * @throws RiotNotFoundException if the location is not found - the model is unchanged.
+     */
+    public static void read(Model model, String uri, String base, Lang2 hintLang, Context context)
+    {
+        Graph g = model.getGraph() ;
+        Sink<Triple> sink = new SinkTriplesToGraph(g) ;
+        readTriples(sink, uri, base, hintLang, context) ;
+    }
+
+    /** Read triples into a Model with bytes from an InputStream.
+     *  A base URI and a syntax can be provided.
+     *  The base URI defualts to "no base" in which case the data should have no relative URIs.
+     *  The lang gives the syntax of the stream. 
+     * @param model     Destination for the RDF read.
+     * @param in        InputStream
+     * @param lang      Language syntax
+     */
+
+    public static void read(Model model, InputStream in, Lang2 lang)
+    {
+        read(model, in, null, lang) ;
+    }
+        
+    /** Read triples into a Model with bytes from an InputStream.
+     *  A base URI and a syntax can be provided.
+     *  The base URI defualts to "no base" in which case the data should have no relative URIs.
+     *  The lang gives the syntax of the stream. 
+     * @param model     Destination for the RDF read.
+     * @param in        InputStream
+     * @param base      Base URI 
+     * @param lang      Language syntax
+     */
+    public static void read(Model model, InputStream in, String base, Lang2 lang)
+    {
+        Graph g = model.getGraph() ;
+        Sink<Triple> sink = new SinkTriplesToGraph(g) ;
+        processTriples(sink, base, new TypedInputStream2(in), lang, null) ;
+    }
+
+    /** Read triples into a model with chars from an Reader.
+     * Use java.io.Readers is not encouraged - use with a StringReader is the primary use case.
+     * For files, open a {@link java.io.FileInputStream} to ensure correct character set handling.
+     * @deprecated Use an InputStream or StringReader.
+     * @param model     Destination for the RDF read.
+     * @param in        Reader
+     * @param base      Base URI 
+     * @param lang      Language syntax
+     */
+    @Deprecated
+    public static void read(Model model, Reader in, String base, Lang2 lang)
+    {
+        Graph g = model.getGraph() ;
+        Sink<Triple> sink = new SinkTriplesToGraph(g) ;
+        processTriples(sink, base, in, lang, null) ;
+    }
+
+    /** Read triples into a model with chars from a StringReader.
+     * @param model     Destination for the RDF read.
+     * @param in        InputStream
+     * @param base      Base URI 
+     * @param lang      Language syntax
+     */
+    public static void read(Model model, StringReader in, String base, Lang2 lang)
+    {
+        Graph g = model.getGraph() ;
+        Sink<Triple> sink = new SinkTriplesToGraph(g) ;
+        processTriples(sink, base, in, lang, null) ;
+    }
+
+    
+    /** Read quads into a Dataset from the given location, with hint of langauge.
+     * @see #read(Dataset, String, String, Lang2, Context) 
+     * @param dataset   Destination
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Language syntax
+     */
+    public static void read(Dataset dataset, String uri, Lang2 hintLang)
+    {
+        read(dataset, uri, hintLang, null) ;
+    }
+
+    /** Read quads or triples into a Dataset from the given location. 
+     * @see #read(Dataset, String, String, Lang2, Context) 
+     * @param dataset   Destination
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Language syntax
+     */
+    public static void read(Dataset dataset, String uri, Lang2 hintLang, Context context)
+    {
+        read(dataset, uri, uri, hintLang, context) ;
+    }
+    
+    /** Read quads or triples into a Dataset from the given location.
+     * @see #read(Dataset, String, String, Lang2, Context) 
+     * @param dataset   Destination
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Language syntax
+    *  @throws RiotNotFoundException if the location is not found - the model is unchanged.
+    *  Throws parse errors depending on the language and reader; the Model model may be partially updated. 
+    */ 
+
+    public static void read(Dataset dataset, String uri, String base, Lang2 hintLang, Context context)
+    {
+        DatasetGraph dsg = dataset.asDatasetGraph() ;
+        Sink<Quad> sink = new SinkQuadsToDataset(dsg) ;
+        readQuads(sink, uri, base, hintLang, context) ;
+    }
+
+    /** Read quads or triples into a dataset with bytes from an input stream.
+     * @param dataset   Destination
+     * @param in        InputStream
+     * @param lang      Language syntax
+     */
+    public static void read(Dataset dataset, InputStream in, Lang2 lang)
+    {
+        read(dataset, in, null, lang) ;
+    }
+    
+    /** Read quads or triples into a dataset with bytes from an input stream.
+     * @param dataset   Destination
+     * @param in        InputStream
+     * @param base      Base URI
+     * @param lang      Language syntax
+     */
+    public static void read(Dataset dataset, InputStream in, String base, Lang2 lang)
+    {
+        DatasetGraph dsg = dataset.asDatasetGraph() ;
+        Sink<Quad> sink = new SinkQuadsToDataset(dsg) ;
+        processQuads(sink, base, new TypedInputStream2(in), lang, null) ;
+    }
+    
+    /** Read quads into a dataset with chars from an Reader.
+     * Use java.io.Readers is not encouraged - use with a StringReader is the primary use case.
+     * For files, open a {@link java.io.FileInputStream} to ensure correct character set handling.
+     * @param dataset   Destination
+     * @param in        InputStream
+     * @param base      Base URI
+     * @param lang      Language syntax
+     * @deprecated use an InputStream or a StringReader.
+     */
+    @Deprecated
+    public static void read(Dataset dataset, Reader in, String base, Lang2 lang)
+    {
+        DatasetGraph dsg = dataset.asDatasetGraph() ;
+        Sink<Quad> sink = new SinkQuadsToDataset(dsg) ;
+        processQuads(sink, base, in, lang, null) ;
+    }
+
+    /** Read quads into a dataset with chars from a StringReader.
+     * Use java.io.Readers is not encouraged - use with a StringReader is the primary use case.
+     * For files, open a {@link java.io.FileInputStream} to ensure correct character set handling.
+     * @param dataset   Destination
+     * @param in        InputStream
+     * @param base      Base URI
+     * @param lang      Language syntax
+     */
+    public static void read(Dataset dataset, StringReader in, String base, Lang2 lang)
+    {
+        DatasetGraph dsg = dataset.asDatasetGraph() ;
+        Sink<Quad> sink = new SinkQuadsToDataset(dsg) ;
+        processQuads(sink, base, in, lang, null) ;
+    }
+
+//    public static void addTripleSyntax(Lang2 language, ContentType contentType, ReaderRIOTFactory<Triple> factory, String ... fileExt )
+//    { 
+//        Langs.addTripleSyntax$(language, contentType, factory, fileExt) ;
+//    } 
+//    
+//    public static void addQuadSyntax(Lang2 language, ContentType contentType, ReaderRIOTFactory<Quad> factory, String ... fileExt )
+//    {
+//        Langs.addQuadSyntax$(language, contentType, factory, fileExt) ;
+//    }
+    
+    /** Read triples - send to a sink.
+     * @param sink     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+     */
+    public static void readTriples(Sink<Triple> sink, String uri, Lang2 hintLang, Context context)
+    {
+        readTriples(sink, uri, uri, hintLang, context) ;
+    }
+    
+    /** Read triples - send to a sink.
+     * @param sink     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param base      Base URI (defaults to uri).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+     */
+    public static void readTriples(Sink<Triple> sink, String uri, String base, Lang2 hintLang, Context context)
+    {
+        TypedInputStream2 in = open(uri, context) ;
+        if ( in == null )
+            throw new RiotException("Not found: "+uri) ;
+        processTriples(sink, base, in, hintLang, context) ;
+        in.close() ;
+    }
+    
+    /** Read quads - send to a sink.
+     * @param sink     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+     */
+    public static void readQuads(Sink<Quad> sink, String uri, Lang2 hintLang, Context context)
+    {
+        readQuads(sink, uri, uri, hintLang, context) ;
+    }
+
+    /** Read quads - send to a sink.
+     * @param sink     Destination for the RDF read.
+     * @param uri       URI to read from (includes file: and a plain file name).
+     * @param base      Base URI (defaults to uri).
+     * @param hintLang  Hint for the syntax
+     * @param context   Content object to control reading process.
+     */
+    public static void readQuads(Sink<Quad> sink, String uri, String base, Lang2 hintLang, Context context)
+    {
+        TypedInputStream2 in = open(uri, context) ;
+        if ( in == null )
+            throw new RiotException("Not found: "+uri) ;
+        processQuads(sink, base, in, hintLang, context) ;
+        in.close() ;
+    }
+
+    /** Open a stream to the destination (URI or filename)
+     * Performs content negotition, including looking at file extension. 
+     */
+    public static TypedInputStream2 open(String filenameOrURI)
+    { return open(filenameOrURI, (Context)null) ; }
+    
+    /** Open a stream to the destination (URI or filename)
+     * Performs content negotition, including looking at file extension. 
+     */
+    public static TypedInputStream2 open(String filenameOrURI, Context context)
+    {
+        StreamManager sMgr = StreamManager.get() ;
+        if ( context != null )
+        {
+            try { sMgr = (StreamManager)context.get(streamManagerSymbol, context) ; }
+            catch (ClassCastException ex) 
+            { log.warn("Context symbol '"+streamManagerSymbol+"' is not a "+Utils.classShortName(StreamManager.class)) ; }
+        }
+        
+        return open(filenameOrURI, sMgr) ;
+    }
+    
+    public static TypedInputStream2 open(String filenameOrURI, StreamManager sMgr)
+    {
+        TypedInputStream2 in = sMgr.open(filenameOrURI) ;
+            
+        if ( in == null )
+        {
+            if ( log.isDebugEnabled() )
+                //log.debug("Found: "+filenameOrURI+" ("+loc.getName()+")") ;
+                log.debug("Not Found: "+filenameOrURI) ;
+            throw new RiotNotFoundException("Not found: "+filenameOrURI) ;
+            //return null ;
+        }
+        if ( log.isDebugEnabled() )
+            //log.debug("Found: "+filenameOrURI+" ("+loc.getName()+")") ;
+            log.debug("Found: "+filenameOrURI) ;
+        return in ;
+    }
+    
+    // ----- 
+    // Readers are algorithms and must be stateless (or they must create a per run
+    // instance of something) because they may be called concurrency from different threads.
+    // The Context Readerobject gives the per-run configuration.  
+    
+    // Alternative: A two step factory-instance design means
+    // readers can be created and passed around (e,.g. to set specific features)
+    // We could have had two step design - ReaderFactory-ReaderInstance
+    // no - put the bruden on complicated readers, not everyone. 
+    
+    private static void processTriples(Sink<Triple> sink, String baseUri, TypedInputStream2 in, Lang2 hintLang, Context context)
+    {
+        ContentType ct = determineCT(baseUri, in.getContentType(), hintLang ) ;
+        
+        if ( ct == null )
+            throw new RiotException("Failed to determine the triples content type: (URI="+baseUri+" : stream="+in.getContentType()+" : hint="+hintLang+")") ;
+
+        ReaderRIOT<Triple> reader = getReaderTriples(ct) ;
+        if ( reader == null )
+            throw new RiotException("No triples reader for content type: "+ct.getContentType()) ;
+        
+        reader.read(in.getInput(), baseUri, ct, sink, context) ;
+    }
+
+    private static ReaderRIOT<Triple> getReaderTriples(ContentType ct)
+    {
+        Lang2 lang = Langs.contentTypeToLang(ct) ;
+        ReaderRIOTFactory<Triple> r = Langs.getFactoryTriples(lang) ;
+        if ( r == null )
+            return null ;
+        return r.create(lang) ;
+    }
+
+    // java.io.Readers are NOT preferred.
+    @SuppressWarnings("deprecation")
+    private static void processTriples(Sink<Triple> sink, String base, Reader in, Lang2 hintLang, Context context)
+    {
+        // Not as good as from an InputStream - RDF/XML not supported 
+        ContentType ct = determineCT(base, null, hintLang) ;
+        if ( ct == null )
+            throw new RiotException("Failed to determine the triples content type: (URI="+base+" : hint="+hintLang+")") ;
+        
+        Tokenizer tokenizer = TokenizerFactory.makeTokenizer(in) ;
+        if ( hintLang == null )
+            throw new RiotException("No language specificied") ;
+        Lang lang = Langs.convert(hintLang) ;
+        LangRIOT parser ;
+        if ( lang == Lang.RDFXML )
+            parser = LangRDFXML.create(in, base, base, ErrorHandlerFactory.errorHandlerStd, sink) ;
+        else
+            parser = RiotReader.createParserTriples(tokenizer, lang, base, sink) ;
+        parser.parse() ;
+    }
+    
+    private static void processQuads(Sink<Quad> sink, String uri, TypedInputStream2 in, Lang2 hintLang, Context context)
+    {
+        ContentType ct = determineCT(uri, in.getContentType(), hintLang ) ;
+        if ( ct == null )
+            throw new RiotException("Failed to determine the quads content type: (URI="+uri+" : stream="+in.getContentType()+" : hint="+hintLang+")") ;
+        ReaderRIOT<Quad> reader = getReaderQuads(ct) ;
+        if ( reader == null )
+            throw new RiotException("No quads reader for content type: "+ct) ;
+        
+        reader.read(in.getInput(), uri, ct, sink, context) ;
+    }
+
+    private static ReaderRIOT<Quad> getReaderQuads(ContentType ct)
+    {
+        Lang2 lang = Langs.contentTypeToLang(ct) ;
+        ReaderRIOTFactory<Quad> r = Langs.getFactoryQuads(lang) ;
+        if ( r == null )
+            return null ;
+        return r.create(lang) ;
+    }
+    
+    // java.io.Readers are NOT preferred.
+    private static void processQuads(Sink<Quad> sink, String base, Reader in, Lang2 hintLang, Context context)
+    {
+        Tokenizer tokenizer = TokenizerFactory.makeTokenizer(in) ;
+        Lang lang = Langs.convert(hintLang) ;
+        LangRIOT parser = RiotReader.createParserQuads(tokenizer, lang, base, sink) ;
+        parser.parse() ;
+    }
+
+    private static ContentType determineCT(String target, String ctStr, Lang2 hintLang)
+    {
+        if ( ctStr != null )
+            ctStr = WebContent.contentTypeCanonical(ctStr) ;
+        
+        boolean isTextPlain = WebContent.contentTypeTextPlain.equals(ctStr) ;
+        ContentType ct = (ctStr==null) ? null : ContentType.parse(ctStr) ;
+        
+        // It's it's text plain, we ignore it because a lot of naive
+        // server setups return text/plain for any file type.
+        
+        if ( ct == null || isTextPlain )
+        {
+            if ( hintLang == null )
+                ct = Langs.guessContentType(target) ;
+            else
+            {
+                ct = hintLang.getContentType() ;
+//                if ( ct == null )
+//                {
+//                    // Is the hint a content type?
+//                    Lang2 lang = Langs.contentTypeToLang(hintLang) ;
+//                    if ( lang != null )
+//                        ct = lang.getContentType() ;
+//                }
+            }
+        }
+        return ct ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterFileManager.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterFileManager.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterFileManager.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterFileManager.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,338 @@
+/*
+ * 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.IOException ;
+import java.io.InputStream ;
+import java.util.Iterator ;
+
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.apache.jena.riot.stream.* ;
+import org.openjena.atlas.lib.IRILib ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.shared.NotFoundException ;
+import com.hp.hpl.jena.util.FileUtils ;
+import com.hp.hpl.jena.util.LocationMapper ;
+import com.hp.hpl.jena.util.TypedStream ;
+
+/** 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 LocatorFile2}, one {@link LocatorClassLoader} and
+ * one {@link LocatorURL2}
+ * 
+ * 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 LocatorFile2} also supports the idea of "current directory".
+ * 
+ * @see StreamManager
+ * @see LocationMapper
+ * @see FileUtils
+ */
+ 
+public class AdapterFileManager extends com.hp.hpl.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 FileManager */
+    private AdapterFileManager()
+    { 
+        streamManager = new StreamManager() ;
+    }
+    
+    /** Create a new file manager that is a copy of another.
+     * Location mapper and locators chain are copied (the locators are not cloned).
+     * @param filemanager
+     */
+    public AdapterFileManager(com.hp.hpl.jena.util.FileManager filemanager)
+    {
+        this() ;
+        Iterator<com.hp.hpl.jena.util.Locator> iter = filemanager.locators() ;
+        while ( iter.hasNext() )
+            streamManager.addLocator(AdapterLib.convert(iter.next())) ;
+
+        LocationMapper locmap = filemanager.getLocationMapper() ;
+        streamManager.setLocationMapper(AdapterLib.copyConvert(locmap)) ;
+    }
+
+    public AdapterFileManager(StreamManager streamManager)
+    {
+        this(streamManager, (LocationMapper2)null) ;
+    }
+    
+    /** Create a FileManger using a RIOT StreamManager and RIOT LocationMapper  */
+    public AdapterFileManager(StreamManager streamManager, LocationMapper2 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(), (LocationMapper2)null) ;
+        return fMgr ;
+    }
+    
+    /** Return the associate stream manager */ 
+    public StreamManager getStreamManager()         { return streamManager ; } 
+    
+    /** Set the location mapping */
+    @Override
+    public void setLocationMapper(LocationMapper mapper)   { streamManager.setLocationMapper(AdapterLib.copyConvert(mapper)) ; }
+    
+    /** Get the location mapping */
+    @Override
+    public LocationMapper getLocationMapper()               { return new AdapterLocationMapper(streamManager.getLocationMapper()) ; }
+    
+    /** Return an iterator over all the handlers */
+    @Override
+    public Iterator<com.hp.hpl.jena.util.Locator> locators()    { throw new UnsupportedOperationException() ; }
+
+    /** Remove a locator */ 
+    @Override
+    public void remove(com.hp.hpl.jena.util.Locator loc)                             { throw new UnsupportedOperationException() ; }
+
+    /** Add a locator to the end of the locators list */ 
+    @Override
+    public void addLocator(com.hp.hpl.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)
+    {
+        LocatorFile2 fLoc = new LocatorFile2(dir) ;
+        streamManager.addLocator(fLoc) ;
+    }
+    
+    /** Add a class loader locator */ 
+    @Override
+    public void addLocatorClassLoader(ClassLoader cLoad)
+    {
+        LocatorClassLoader cLoc = new LocatorClassLoader(cLoad) ;
+        streamManager.addLocator(cLoc) ;
+    }
+
+    /** Add a URL locator */
+    @Override
+    public void addLocatorURL()
+    {
+        Locator loc = new LocatorURL2() ;
+        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 getCachingModels()               { return modelCache.getCachingModels() ; }
+    
+    /** 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)
+
+    @Override
+    protected Model readModelWorker(Model model, String filenameOrURI, String baseURI, String syntax)
+    {
+        // Doesn't call open() - we want to make the synatx 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:" ) )
+        {
+            // No syntax, no baseURI, HTTP URL ==> use content negotiation
+            model.read(mappedURI) ;
+            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) ;
+
+        TypedInputStream2 in = streamManager.openNoMapOrNull(mappedURI) ;
+        if ( in == null )
+        {
+            if ( log.isDebugEnabled() )
+                log.debug("Failed to locate '"+mappedURI+"'") ;
+            throw new NotFoundException("Not found: "+filenameOrURI) ;
+        }
+        if ( in.getMediaType() != null )
+        {
+            // XXX
+            //syntax
+        }
+        model.read(in.getInput(), baseURI, syntax) ;
+        try { in.getInput().close(); } catch (IOException ex) {}
+        return model ;
+    }
+
+    private static String chooseBaseURI(String baseURI)
+    {
+        // Use IRILib.filenameToIRI
+        String scheme = FileUtils.getScheme(baseURI) ;
+        
+        if ( scheme != null && ! scheme.equals("file") )
+            // Not file: - leave alone.
+            return baseURI ;
+        
+        return IRILib.filenameToIRI(baseURI) ;
+    }
+    
+    /** Open a file using the locators of this FileManager 
+     *  Throws RiotNotFoundException if not found.*/ 
+    @Override
+    public InputStream open(String filenameOrURI)
+    { 
+        return streamManager.open(filenameOrURI).getInput() ;
+    }
+    
+    /** 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).getInput() ; }
+
+    /** 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)) ; }
+    
+    /** @deprecated Use mapURI */
+    @Deprecated
+    @Override
+    public String remap(String filenameOrURI)
+    { return mapURI(filenameOrURI) ; }
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLib.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLib.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLib.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLib.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,84 @@
+/**
+ * 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.util.Iterator ;
+
+import com.hp.hpl.jena.sparql.util.Utils ;
+
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.apache.jena.riot.stream.* ;
+import org.openjena.riot.RiotException ;
+
+
+class AdapterLib
+{
+    public static com.hp.hpl.jena.util.TypedStream convert(TypedInputStream2 in)
+    {
+        return new com.hp.hpl.jena.util.TypedStream(in.getInput(), in.getContentType(), in.getCharset()) ;
+    }
+    
+    
+    public static LocationMapper2 copyConvert(com.hp.hpl.jena.util.LocationMapper locMap)
+    {
+        LocationMapper2 lmap2 = new LocationMapper2() ;
+        if ( locMap == null )
+            return null ;
+        
+        Iterator<String> sIter1 = locMap.listAltEntries() ;
+        for ( ; sIter1.hasNext() ; )
+        {
+            String k = sIter1.next(); 
+            lmap2.addAltEntry(k, locMap.getAltEntry(k)) ;
+        }
+        
+        Iterator<String> sIter2 = locMap.listAltPrefixes() ;
+
+        for ( ; sIter2.hasNext() ; )
+        {
+            String k = sIter1.next(); 
+            lmap2.addAltEntry(k, locMap.getAltPrefix(k)) ;
+        }
+        return lmap2 ;
+    }
+
+    public static Locator convert(com.hp.hpl.jena.util.Locator oldloc)
+    {
+        if ( oldloc instanceof com.hp.hpl.jena.util.LocatorFile )
+        {
+            com.hp.hpl.jena.util.LocatorFile lFile = (com.hp.hpl.jena.util.LocatorFile)oldloc ;
+            return new LocatorFile2(lFile.getDir()) ;
+        }
+        if ( oldloc instanceof com.hp.hpl.jena.util.LocatorClassLoader )
+        {
+            com.hp.hpl.jena.util.LocatorClassLoader classLoc = (com.hp.hpl.jena.util.LocatorClassLoader)oldloc ;
+            return new LocatorClassLoader(classLoc.getClassLoader()) ;
+        }
+        if ( oldloc instanceof com.hp.hpl.jena.util.LocatorURL )
+            return new LocatorURL2() ;
+        if ( oldloc instanceof com.hp.hpl.jena.util.LocatorZip )
+        {
+            com.hp.hpl.jena.util.LocatorZip zipLoc = (com.hp.hpl.jena.util.LocatorZip)oldloc ;
+            return new LocatorZip(zipLoc.getZipFileName()) ;
+        }
+        
+        throw new RiotException("Unrecognized Locator: "+Utils.className(oldloc)) ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocationMapper.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocationMapper.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocationMapper.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocationMapper.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,74 @@
+/**
+ * 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.util.Iterator ;
+
+import org.apache.jena.riot.stream.LocationMapper2 ;
+
+import com.hp.hpl.jena.rdf.model.Model ;
+
+/** Adapter from Jena2 LocationMapper to RIOT LocationMapper */ 
+public class AdapterLocationMapper extends com.hp.hpl.jena.util.LocationMapper 
+{
+    private final LocationMapper2 mapper ;
+
+    public AdapterLocationMapper(LocationMapper2 mapper) {  this.mapper = mapper ; }
+    
+    @Override
+    public String altMapping(String uri, String otherwise)  { return mapper.altMapping(uri, otherwise) ; }
+
+    @Override
+    public void addAltEntry(String uri, String alt)         { mapper.addAltEntry(uri, alt) ; }
+
+    @Override
+    public void addAltPrefix(String uriPrefix, String altPrefix)    { mapper.addAltPrefix(uriPrefix, altPrefix) ; } 
+
+    /** Iterate over all the entries registered */ 
+    @Override
+    public Iterator<String> listAltEntries()  { return mapper.listAltEntries() ; } 
+    /** Iterate over all the prefixes registered */ 
+    @Override
+    public Iterator<String> listAltPrefixes() { return mapper.listAltEntries() ; } 
+    
+    @Override
+    public void removeAltEntry(String uri)  { mapper.removeAltEntry(uri) ; }
+
+    @Override
+    public void removeAltPrefix(String uriPrefix)   { mapper.removeAltPrefix(uriPrefix) ; }
+
+    @Override
+    public String getAltEntry(String uri)           { return mapper.getAltEntry(uri) ; } 
+
+    @Override
+    public String getAltPrefix(String uriPrefix)    { return mapper.getAltPrefix(uriPrefix) ; }
+    
+    @Override
+    public int hashCode()               { return mapper.hashCode() ; }
+    
+    @Override
+    public boolean equals(Object obj)   { return mapper.equals(obj) ; }
+    
+    @Override
+    public String toString()            { return mapper.toString() ; } 
+    
+    @Override
+    public void toModel(Model model)    { mapper.toModel(model) ; }
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocator.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocator.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/AdapterLocator.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,43 @@
+/**
+ * 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 org.apache.jena.riot.TypedInputStream2 ;
+import org.apache.jena.riot.stream.Locator ;
+
+public class AdapterLocator implements com.hp.hpl.jena.util.Locator
+{
+    private final Locator locator ;
+
+    public AdapterLocator(Locator locator) { this.locator = locator ; }
+
+    @Override
+    public com.hp.hpl.jena.util.TypedStream open(String filenameOrURI)
+    {
+        TypedInputStream2 in = locator.open(filenameOrURI) ;
+        return AdapterLib.convert(in) ;
+    }
+
+    @Override
+    public String getName()
+    {
+        return locator.getName() ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/FileManagerModelCache.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/FileManagerModelCache.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/FileManagerModelCache.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/adapters/FileManagerModelCache.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,78 @@
+/**
+ * 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.util.HashMap ;
+import java.util.Map ;
+
+import com.hp.hpl.jena.rdf.model.Model ;
+
+// Legacy support.
+class FileManagerModelCache {
+    boolean cacheModelLoads = false ;
+    Map<String, Model> modelCache = null ;
+    // -------- Cache operations
+    
+    /** Reset the model cache */
+    public void resetCache()
+    {
+        if ( modelCache != null )
+            modelCache.clear() ;
+    }
+    
+    /** Change the state of model cache : does not clear the cache */ 
+    public void setModelCaching(boolean state)
+    {
+        cacheModelLoads = state ;
+        if ( cacheModelLoads && modelCache == null )
+            modelCache = new HashMap<String, Model>() ;
+    }
+    
+    /** return whether caching is on of off */
+    public boolean getCachingModels() { return cacheModelLoads ; }
+    
+    /** Read out of the cache - return null if not in the cache */ 
+    public Model getFromCache(String filenameOrURI)
+    { 
+        if ( ! getCachingModels() )
+            return null; 
+        return modelCache.get(filenameOrURI) ;
+    }
+    
+    public boolean hasCachedModel(String filenameOrURI)
+    { 
+        if ( ! getCachingModels() )
+            return false ; 
+        return modelCache.containsKey(filenameOrURI) ;
+    }
+    
+    public void addCacheModel(String uri, Model m)
+    { 
+        if ( getCachingModels() )
+            modelCache.put(uri, m) ;
+    }
+
+    public void removeCacheModel(String uri)
+    { 
+        if ( getCachingModels() )
+            modelCache.remove(uri) ;
+    }
+
+
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/JenaIOEnvironment.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/JenaIOEnvironment.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/JenaIOEnvironment.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/JenaIOEnvironment.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,199 @@
+/*
+ * 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.stream;
+
+import java.util.StringTokenizer ;
+
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.apache.jena.riot.adapters.AdapterFileManager ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.JenaRuntime ;
+import com.hp.hpl.jena.rdf.model.* ;
+import com.hp.hpl.jena.shared.JenaException ;
+import com.hp.hpl.jena.util.FileUtils ;
+import com.hp.hpl.jena.vocabulary.LocationMappingVocab ;
+
+/** Code for using the general facilities of the location mapper/ filemanager subsystem
+ *  and set up for Jena usage. e.g. find a location mapper with RDf description. 
+ */
+class JenaIOEnvironment
+{
+    static LocationMapper2 theMapper = null ;
+    /** Get the global LocationMapper */
+    public static LocationMapper2 getLocationMapper()
+    {
+        if ( theMapper == null )
+        {
+            theMapper = new LocationMapper2() ;
+            if ( getGlobalConfigPath() != null )
+                JenaIOEnvironment.createLocationMapper(getGlobalConfigPath()) ;
+        }
+        return theMapper ;
+    }
+    
+    static Logger log = LoggerFactory.getLogger(JenaIOEnvironment.class)  ;
+    
+    /** The default path for searching for the location mapper */
+    public static final String DEFAULT_PATH =
+        "file:location-mapping.rdf;file:location-mapping.n3;file:location-mapping.ttl;"+
+        "file:etc/location-mapping.rdf;file:etc/location-mapping.n3;"+
+        "file:etc/location-mapping.ttl" ;
+    public static final String GlobalMapperSystemProperty1 = "http://jena.hpl.hp.com/2004/08/LocationMap" ;
+    public static final String GlobalMapperSystemProperty2 = "LocationMap" ;
+
+    static String s_globalMapperPath = null ; 
+
+    static private String getGlobalConfigPath()
+    {
+        if ( s_globalMapperPath == null )
+            s_globalMapperPath = JenaRuntime.getSystemProperty(GlobalMapperSystemProperty1,null) ;
+        if ( s_globalMapperPath == null )
+            s_globalMapperPath = JenaRuntime.getSystemProperty(GlobalMapperSystemProperty2,null) ;
+        if ( s_globalMapperPath == null )
+            s_globalMapperPath = DEFAULT_PATH ;
+        return s_globalMapperPath ;
+    }
+
+    /** Set the global lcoation mapper. (as returned by get())
+     * If called before any call to get(), then the usual default global location mapper is not created 
+     * @param globalLocationMapper
+     */
+    public static void setGlobalLocationMapper(LocationMapper2 globalLocationMapper)
+    {
+        theMapper = globalLocationMapper ;
+    }
+
+    /** Make a location mapper from the path settings */ 
+    static public LocationMapper2 makeGlobal()
+    {
+        LocationMapper2 lMap = new LocationMapper2() ;
+        if ( getGlobalConfigPath() != null )
+        {
+            LocationMapper2 lMap2 = JenaIOEnvironment.createLocationMapper(getGlobalConfigPath()) ;
+            lMap.copyFrom(lMap2) ;
+        }
+        return lMap ;
+    }
+  
+    /** Create a LocationMapper based on Model */
+    public static LocationMapper2 processConfig(Model m)
+    {
+        LocationMapper2 locMap = new LocationMapper2() ; 
+        StmtIterator mappings =
+            m.listStatements(null, LocationMappingVocab.mapping, (RDFNode)null) ;
+    
+        for (; mappings.hasNext();)
+        {
+            Statement s = mappings.nextStatement() ;
+            Resource mapping =  s.getResource() ;
+            
+            if ( mapping.hasProperty(LocationMappingVocab.name) )
+            {
+                try 
+                {
+                    String name = mapping.getRequiredProperty(LocationMappingVocab.name)
+                                        .getString() ;
+                    String altName = mapping.getRequiredProperty(LocationMappingVocab.altName)
+                                        .getString() ;
+                    locMap.addAltEntry(name, altName) ;
+                    log.debug("Mapping: "+name+" => "+altName) ;
+                } catch (JenaException ex)
+                {
+                    log.warn("Error processing name mapping: "+ex.getMessage()) ;
+                    throw ex ;
+                }
+            }
+            
+            if ( mapping.hasProperty(LocationMappingVocab.prefix) )
+            {
+                try 
+                {
+                    String prefix = mapping.getRequiredProperty(LocationMappingVocab.prefix)
+                                        .getString() ;
+                    String altPrefix = mapping.getRequiredProperty(LocationMappingVocab.altPrefix)
+                                        .getString() ;
+                    locMap.addAltPrefix(prefix, altPrefix) ;
+                    log.debug("Prefix mapping: "+prefix+" => "+altPrefix) ;
+                } catch (JenaException ex)
+                {
+                    log.warn("Error processing prefix mapping: "+ex.getMessage()) ;
+                    throw ex ;
+                }
+            }
+        }
+        return locMap ;
+    }
+
+    /** Search a path (which is delimited by ";" because ":" is used in URIs)
+     *  to find a description of a LocationMapper, then create and return a
+     *  LocationMapper based on the description.
+     */
+    public static LocationMapper2 createLocationMapper(String configPath)
+    {
+        // Old code : maintenance: use Webreader to open the model. 
+        
+        LocationMapper2 locMap = new LocationMapper2() ;
+        if ( configPath == null || configPath.length() == 0 )
+        {
+            log.warn("Null configuration") ;
+            return null ;
+        }
+        
+        // Make a file manager to look for the location mapping file
+        StreamManager smgr = new StreamManager() ;
+        smgr.addLocator(new LocatorFile2()) ;
+        smgr.addLocator(new LocatorClassLoader(smgr.getClass().getClassLoader())) ;
+        
+        try {
+            String uriConfig = null ; 
+            TypedInputStream2 in = null ;
+            
+            StringTokenizer pathElems = new StringTokenizer( configPath, AdapterFileManager.PATH_DELIMITER );
+            while (pathElems.hasMoreTokens()) {
+                String uri = pathElems.nextToken();
+                if ( uri == null || uri.length() == 0 )
+                    break ;
+                
+                in = smgr.openNoMapOrNull(uri) ;
+                if ( in != null )
+                {
+                    uriConfig = uri ;
+                    break ;
+                }
+            }
+    
+            if ( in == null )
+            {
+                log.debug("Failed to find configuration: "+configPath) ;
+                return null ;
+            }
+            String syntax = FileUtils.guessLang(uriConfig) ;
+            Model model = ModelFactory.createDefaultModel() ;
+            model.read(in.getInput(), uriConfig, syntax) ;
+            processConfig(model) ;
+        } catch (JenaException ex)
+        {
+            LoggerFactory.getLogger(LocationMapper2.class).warn("Error in configuration file: "+ex.getMessage()) ;
+        }
+        return locMap ;
+    }
+
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocationMapper2.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocationMapper2.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocationMapper2.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocationMapper2.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,241 @@
+/*
+ * 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.stream;
+
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+import com.hp.hpl.jena.rdf.model.Resource ;
+import com.hp.hpl.jena.vocabulary.LocationMappingVocab ;
+
+/** 
+ * Alternative locations for URIs.  Maintains two maps:
+ * single item alternatives and alternative prefixes.
+ * To suggest an alternative location, first check the single items,
+ * then check the prefixes.
+ *    
+ * A LocationMapper can be configured by an RDF file.  The default for this
+ * is "etc/location-mapping.n3".
+ * 
+ * There is a default LocationMapper which is used by the global @link{FileManager}.
+ */
+
+public class LocationMapper2
+{
+    static Logger log = LoggerFactory.getLogger(LocationMapper2.class)  ;
+    Map<String, String> altLocations = new HashMap<String, String>() ;
+    Map<String, String> altPrefixes = new HashMap<String, String>() ;
+    
+    /** Create a LocationMapper with no mapping yet */
+    public LocationMapper2() { }
+    
+    /** Create a LocationMapper made like another one
+     * This is a deep copy of the location and prefix maps..*/
+    public LocationMapper2(LocationMapper2 locMapper)
+    {
+        altLocations.putAll(locMapper.altLocations) ;
+        altPrefixes.putAll(locMapper.altPrefixes) ;
+    }
+    
+    // Moved to Jena IO environment setup.
+//    /** Create a LocationMapper from an existing model
+//     * @see com.hp.hpl.jena.vocabulary.LocationMappingVocab
+//     */
+//    public LocationMapper(Model model)
+//    {
+//        LocationMapper lm = JenaIOEnvironment.processConfig(model) ;
+//        if ( lm == null )
+//            throw new AtlasException("Model does not provide a location mapping") ;
+//        copyFrom(lm) ;
+//         
+//    }
+//    
+//    /** Create a LocationMapper from a config file */
+//    public LocationMapper(String config)
+//    {
+//        LocationMapper lm = JenaIOEnvironment.createLocationMapper(config) ;
+//        if ( lm == null )
+//            throw new AtlasException("Config does not provide a location mapping") ;
+//        copyFrom(lm) ;
+//    }
+    
+    public void copyFrom(LocationMapper2 lmap2)
+    {
+        this.altLocations.putAll(lmap2.altLocations) ;
+        this.altPrefixes.putAll(lmap2.altPrefixes) ;
+    }
+    
+    public String altMapping(String uri)
+    {
+        return altMapping(uri, uri) ;
+    }
+
+    /** Apply mappings: first try for an exact alternative location, then
+     *  try to remap by prefix, finally, try the special case of filenames
+     *  in a specific base directory. 
+     * @param uri
+     * @param otherwise
+     * @return The alternative location choosen
+     */
+    public String altMapping(String uri, String otherwise)
+    {
+        if ( altLocations.containsKey(uri)) 
+            return altLocations.get(uri) ;
+        String newStart = null ;
+        String oldStart = null ;
+        for ( Iterator<String> iter = altPrefixes.keySet().iterator() ; iter.hasNext() ;)
+        {
+            String prefix = iter.next() ;
+            if ( uri.startsWith(prefix) )
+            {
+                String s = altPrefixes.get(prefix) ;
+                if ( newStart == null || newStart.length() < s.length() )
+                {
+                    oldStart = prefix ;
+                    newStart = s ;
+                }
+            }
+        }
+        
+        if ( newStart != null )
+            return newStart+uri.substring(oldStart.length()) ;
+        
+        return otherwise ;
+    }
+    
+
+    public void addAltEntry(String uri, String alt)
+    {
+        altLocations.put(uri, alt) ;
+    }
+
+    public void addAltPrefix(String uriPrefix, String altPrefix) 
+    {
+        altPrefixes.put(uriPrefix, altPrefix) ;
+    }
+
+    /** Iterate over all the entries registered */ 
+    public Iterator<String> listAltEntries()  { return altLocations.keySet().iterator() ; } 
+    /** Iterate over all the prefixes registered */ 
+    public Iterator<String> listAltPrefixes() { return altPrefixes.keySet().iterator() ; } 
+    
+    public void removeAltEntry(String uri)
+    {
+        altLocations.remove(uri) ;
+    }
+
+    public void removeAltPrefix(String uriPrefix) 
+    {
+        altPrefixes.remove(uriPrefix) ;
+    }
+    public String getAltEntry(String uri)
+    {
+        return altLocations.get(uri) ;
+    }
+
+    public String getAltPrefix(String uriPrefix) 
+    {
+        return altPrefixes.get(uriPrefix) ;
+    }
+   
+    @Override
+    public int hashCode()
+    {
+        int x = 0 ;
+        x = x ^ altLocations.hashCode() ;
+        x = x ^ altPrefixes.hashCode() ;
+        return x ;
+    }
+    
+    @Override
+    public boolean equals(Object obj)
+    {
+        if ( ! ( obj instanceof LocationMapper2 ) )
+            return false ;
+        LocationMapper2 other = (LocationMapper2)obj ;
+        
+        if ( ! this.altLocations.equals(other.altLocations) )
+            return false ;
+        
+        if ( ! this.altPrefixes.equals(other.altPrefixes) )
+            return false ;
+        return true ; 
+    }
+    
+    @Override
+    public String toString()
+    {
+        String s = "" ;
+        for ( Iterator<String> iter = altLocations.keySet().iterator() ; iter.hasNext() ; )
+        {
+            String k = iter.next() ;
+            String v = altLocations.get(k) ;
+            s = s+"(Loc:"+k+"=>"+v+") " ;
+        }
+
+        for ( Iterator<String> iter = altPrefixes.keySet().iterator() ; iter.hasNext() ; )
+        {
+            String k = iter.next() ;
+            String v = altPrefixes.get(k) ;
+            s = s+"(Prefix:"+k+"=>"+v+") " ;
+        }
+        return s ;
+    }
+    
+    public Model toModel()
+    {
+        Model m = ModelFactory.createDefaultModel() ;
+        m.setNsPrefix("lmap", "http://jena.hpl.hp.com/2004/08/location-mapping#") ;
+        toModel(m) ;
+        return m ;
+    }
+    
+    public void toModel(Model model)
+    {
+        
+        for ( Iterator<String> iter = altLocations.keySet().iterator() ; iter.hasNext() ; )
+        {
+            Resource r = model.createResource() ;
+            Resource e = model.createResource() ;
+            model.add(r, LocationMappingVocab.mapping, e) ;
+            
+            String k = iter.next() ;
+            String v = altLocations.get(k) ;
+            model.add(e, LocationMappingVocab.name, k) ;
+            model.add(e, LocationMappingVocab.altName, v) ;
+        }
+
+        for ( Iterator<String> iter = altPrefixes.keySet().iterator() ; iter.hasNext() ; )
+        {
+            Resource r = model.createResource() ;
+            Resource e = model.createResource() ;
+            model.add(r, LocationMappingVocab.mapping, e) ;
+            String k = iter.next() ;
+            String v = altPrefixes.get(k) ;
+            model.add(e, LocationMappingVocab.prefix, k) ;
+            model.add(e, LocationMappingVocab.altPrefix, v) ;
+        }
+    }
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/Locator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/Locator.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/Locator.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/Locator.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,32 @@
+/*
+ * 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.stream;
+
+import org.apache.jena.riot.TypedInputStream2 ;
+
+/**
+ *  Interface to things that open TypedStreams from a place
+ */
+
+public interface Locator
+{
+    // Open a stream given a name of some kind (not necessarily an IRI).
+    public TypedInputStream2 open(String uri) ;
+    public String getName() ;
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorClassLoader.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorClassLoader.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorClassLoader.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorClassLoader.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,81 @@
+/*
+ * 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.stream;
+
+import java.io.InputStream ;
+
+import org.apache.jena.riot.Langs ;
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.openjena.atlas.web.ContentType ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class LocatorClassLoader  implements Locator
+{
+    static Logger log = LoggerFactory.getLogger(LocatorClassLoader.class) ;
+
+    private final ClassLoader classLoader ;
+    public LocatorClassLoader(ClassLoader _classLoader)
+    {
+        classLoader =_classLoader ;
+    }
+    
+    @Override
+    public boolean equals( Object other )
+    {
+        return 
+            other instanceof LocatorClassLoader 
+            && classLoader == ((LocatorClassLoader) other).classLoader;
+    }
+    
+    @Override
+    public int hashCode()
+        { return classLoader.hashCode(); }
+    
+    @Override
+    public TypedInputStream2 open(String resourceName)
+    {
+        if ( classLoader == null )
+            return null ;
+            
+        InputStream in = classLoader.getResourceAsStream(resourceName) ;
+        if ( in == null )
+        {
+            if ( StreamManager.logAllLookups && log.isTraceEnabled() )
+                log.trace("Failed to open: "+resourceName) ;
+            return null ;
+        }
+        
+        if ( StreamManager.logAllLookups  && log.isTraceEnabled() )
+            log.trace("Found: "+resourceName) ;
+        
+        ContentType ct = Langs.guessContentType(resourceName) ;
+        // No sensible base URI.
+        return new TypedInputStream2(in, ct, null) ;
+    }
+    
+    public ClassLoader getClassLoader()
+    {
+        return classLoader ;
+    }
+
+    @Override
+    public String getName() { return "ClassLoaderLocator" ; }
+    
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorFile2.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorFile2.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorFile2.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorFile2.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,187 @@
+/*
+ * 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.stream;
+
+import java.io.File ;
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.security.AccessControlException ;
+
+import org.apache.jena.riot.Langs ;
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.openjena.atlas.io.IO ;
+import org.openjena.atlas.lib.IRILib ;
+import org.openjena.atlas.web.ContentType ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.util.FileUtils ;
+
+/** Location files in the filing system.
+ *  A FileLocator can have a "current directory" - this is separate from any
+ *  location mapping (see @link{LocationMapping}) as it applies only to files.
+ */
+
+public class LocatorFile2 implements Locator
+{
+    static Logger log = LoggerFactory.getLogger(LocatorFile2.class) ;
+    private final String thisDir ;
+    private final String thisDirLogStr ;
+
+    /** Create a LocatorFile */
+    public LocatorFile2() { this(null) ; }
+    
+    /** Create a LocatorFile that uses the argument as it's working directory
+     * The working directory should be a UNIX style file name,
+     * (relative or absolute), not a URI.
+     */
+    public LocatorFile2(String dir)
+    {
+        if ( dir != null )
+        {
+            if ( dir.endsWith("/") || dir.endsWith(java.io.File.separator) )
+                dir = dir.substring(0,dir.length()-1) ;
+            thisDirLogStr = " ["+dir+"]" ;
+        }
+        else
+            thisDirLogStr = "" ;
+        thisDir = dir ;
+    }
+
+    // Two LocatorFile are the same if they would look up names to the same files.
+    
+    /** To a File, after processing the filename for file: or relative filename */
+    public String toFileName(String filenameIRI)
+    {
+        // Do not use : it will ignore the directory. 
+        //IRILib.filenameToIRI
+        
+        String scheme = FileUtils.getScheme(filenameIRI) ;
+        String fn = filenameIRI ;
+        // Windows : C:\\ is not a scheme name!
+        if ( scheme != null && scheme.length() > 1 )
+        {
+            if ( ! scheme.equalsIgnoreCase("file") )
+                // Not filename or a file: IRI
+                return null ;
+            fn = IRILib.IRIToFilename(filenameIRI) ;
+        }
+        // fn is the file name to use.
+        // If it is relative, and we have a different working directory, prepend that.  
+        // "/" is a path separator on Windows as well.
+        if ( thisDir != null && ! fn.startsWith("/") && ! fn.startsWith(File.separator) )
+            fn = thisDir+"/"+fn ;
+        return fn ;
+    }
+    
+    public String getThisDir()
+    {
+        return thisDir ;
+    }
+
+    public boolean exists(String fileIRI)
+    {
+        String fn = toFileName(fileIRI) ;
+        if ( fn == null )
+            return false ;
+        
+        return exists$(fn) ;
+    }
+    
+    private boolean exists$(String fn)
+    {
+        return new File(fn).exists() ;
+    }
+
+    /** Open anything that looks a bit like a file name */ 
+    @Override
+    public TypedInputStream2 open(String filenameIRI)
+    {
+        String fn = toFileName(filenameIRI) ;
+        if ( fn == null )
+            return null ;
+        
+        try {
+            if ( ! exists$(fn) )
+            {
+                if ( StreamManager.logAllLookups && log.isTraceEnabled())
+                    log.trace("Not found: "+filenameIRI+thisDirLogStr) ;
+                return null ;
+            }
+        } catch (AccessControlException e) {
+            log.warn("Security problem testing for file", e);
+            return null;
+        }
+        
+        try {
+            InputStream in = IO.openFileEx(fn) ;
+
+            if ( StreamManager.logAllLookups && log.isTraceEnabled() )
+                log.trace("Found: "+filenameIRI+thisDirLogStr) ;
+            
+            ContentType ct = Langs.guessContentType(filenameIRI) ;
+            return new TypedInputStream2(in, ct, filenameIRI) ;
+        } catch (IOException ioEx)
+        {
+            // Includes FileNotFoundException
+            // We already tested whether the file exists or not.
+            log.warn("File unreadable (but exists): "+fn+" Exception: "+ioEx.getMessage()) ;
+            return null ;
+        }
+    }
+    
+    @Override
+    public String getName()
+    {
+        String tmp = "LocatorFile" ;
+        if ( thisDir != null )
+            tmp = tmp+"("+thisDir+")" ;
+        return tmp ;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31 ;
+        int result = 1 ;
+        result = prime * result + ((thisDir == null) ? 0 : thisDir.hashCode()) ;
+        result = prime * result + ((thisDirLogStr == null) ? 0 : thisDirLogStr.hashCode()) ;
+        return result ;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj) return true ;
+        if (obj == null) return false ;
+        if (getClass() != obj.getClass()) return false ;
+        LocatorFile2 other = (LocatorFile2)obj ;
+        if (thisDir == null)
+        {
+            if (other.thisDir != null) return false ;
+        } else
+            if (!thisDir.equals(other.thisDir)) return false ;
+        if (thisDirLogStr == null)
+        {
+            if (other.thisDirLogStr != null) return false ;
+        } else
+            if (!thisDirLogStr.equals(other.thisDirLogStr)) return false ;
+        return true ;
+    }
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorURL2.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorURL2.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorURL2.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorURL2.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,93 @@
+/**
+ * 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.stream;
+
+import com.hp.hpl.jena.util.FileUtils ;
+
+import org.apache.jena.riot.HttpOp2 ;
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class LocatorURL2 implements Locator
+{
+    private static Logger log = LoggerFactory.getLogger(LocatorURL2.class) ;
+    private static final String[] schemeNames = { "http" , "https" } ;    // Must be lower case and not include the ":"
+    
+    public final String acceptTriples = "text/turtle,application/rdf+xml;q=0.9,application/xml;q=0.8,*/*;q=0.5" ; 
+
+    @Override
+    public TypedInputStream2 open(String uri)
+    {
+        if ( ! acceptByScheme(uri) )
+        {
+            if ( StreamManager.logAllLookups && log.isTraceEnabled() )
+                log.trace("Not found : "+uri) ; 
+            return null;
+        }
+        if ( uri.startsWith("http://") || uri.startsWith("https://"))
+            return HttpOp2.execHttpGet(uri, acceptTriples) ;
+        return null ;
+    }
+
+    @Override
+    public String getName()
+    {
+        return "LocatorURL" ;
+    }
+    
+    private static boolean acceptByScheme(String filenameOrURI)
+    {
+        String uriSchemeName = FileUtils.getScheme(filenameOrURI) ;
+        if ( uriSchemeName == null )
+            return false ;
+        uriSchemeName = uriSchemeName.toLowerCase() ; 
+        for ( int i = 0 ; i < schemeNames.length ; i++ )
+        {
+            if ( uriSchemeName.equals(schemeNames[i]) )
+                return true ;
+        }
+        return false ;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31 ;
+        int result = 1 ;
+        result = prime * result + ((acceptTriples == null) ? 0 : acceptTriples.hashCode()) ;
+        return result ;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj) return true ;
+        if (obj == null) return false ;
+        if (getClass() != obj.getClass()) return false ;
+        LocatorURL2 other = (LocatorURL2)obj ;
+        if (acceptTriples == null)
+        {
+            if (other.acceptTriples != null) return false ;
+        } else
+            if (!acceptTriples.equals(other.acceptTriples)) return false ;
+        return true ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorZip.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorZip.java?rev=1410870&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorZip.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/stream/LocatorZip.java Sun Nov 18 11:09:28 2012
@@ -0,0 +1,121 @@
+/*
+ * 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.stream;
+
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.util.zip.ZipEntry ;
+import java.util.zip.ZipFile ;
+
+import org.apache.jena.riot.Langs ;
+import org.apache.jena.riot.TypedInputStream2 ;
+import org.openjena.atlas.web.ContentType ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.shared.JenaException ;
+
+
+/** Location files in a zip file */
+
+public class LocatorZip implements Locator
+{
+    private static Logger log = LoggerFactory.getLogger(LocatorZip.class) ;
+    private final String zipFileName ; 
+    private final ZipFile zipFile ;
+    
+    public LocatorZip(String zfn)
+    {
+        try {
+            zipFileName = zfn ;
+            zipFile = new ZipFile(zipFileName) ;
+        } catch  (IOException ex)
+        { 
+            throw new JenaException("Problems accessing "+zfn, ex) ;
+        }
+    }
+    
+    @Override
+    public TypedInputStream2 open(String filenameOrURI)
+    {
+        ZipEntry entry = zipFile.getEntry(filenameOrURI) ;
+        if ( entry == null )
+        {
+            if ( StreamManager.logAllLookups && log.isDebugEnabled() )
+                log.debug("Not found: "+zipFileName+" : "+filenameOrURI) ; 
+            return null ;
+            
+        }
+        try
+        {
+            InputStream in = zipFile.getInputStream(entry) ;
+            
+            if ( in == null )
+            {
+                if ( StreamManager.logAllLookups && log.isTraceEnabled() )
+                    log.trace("Not found: "+filenameOrURI) ; 
+                return null ;
+            }
+            
+            if ( StreamManager.logAllLookups  && log.isTraceEnabled() )
+                log.trace("Found: "+filenameOrURI) ;
+            
+            ContentType ct = Langs.guessContentType(filenameOrURI) ;
+            return new TypedInputStream2(in, ct, filenameOrURI) ;
+        }
+        catch (IOException ex)
+        {
+            log.warn("IO Exception opening zip entry: " + filenameOrURI);
+            return null;
+        }
+    }
+
+    public String getZipFileName()
+    {
+        return zipFileName ;
+    }
+
+    @Override
+    public String getName() { return "LocatorZip("+zipFileName+")" ; } 
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31 ;
+        int result = 1 ;
+        result = prime * result + ((zipFileName == null) ? 0 : zipFileName.hashCode()) ;
+        return result ;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj) return true ;
+        if (obj == null) return false ;
+        if (getClass() != obj.getClass()) return false ;
+        LocatorZip other = (LocatorZip)obj ;
+        if (zipFileName == null)
+        {
+            if (other.zipFileName != null) return false ;
+        } else
+            if (!zipFileName.equals(other.zipFileName)) return false ;
+        return true ;
+    }
+
+}