Merge pull request #1994 from sszuev/graph-javadocs

jena-core: add more javadocs about Graph-mem thread-safety and ConcurrentModificationException
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index b23d87e..85cb817 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -23,7 +23,7 @@
         os: [ubuntu-latest]
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
     - name: Set up JDK 17
       uses: actions/setup-java@v3
       with:
diff --git a/.github/workflows/maven_macos.yml b/.github/workflows/maven_macos.yml
index 413369c..119a2d5 100644
--- a/.github/workflows/maven_macos.yml
+++ b/.github/workflows/maven_macos.yml
@@ -17,7 +17,7 @@
         os: [macos-latest]
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: Set up JDK
       uses: actions/setup-java@v3
diff --git a/.github/workflows/maven_windows.yml b/.github/workflows/maven_windows.yml
index 8a115b3..986b46e 100644
--- a/.github/workflows/maven_windows.yml
+++ b/.github/workflows/maven_windows.yml
@@ -19,7 +19,7 @@
     # "windows" takes up a lot of diskspace due a longstanding JDK issue
     # Running on c: seems to work.
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: Set up JDK
       uses: actions/setup-java@v3
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangTurtleBase.java b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangTurtleBase.java
index 851734c..863d504 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangTurtleBase.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangTurtleBase.java
@@ -16,153 +16,153 @@
  * limitations under the License.
  */
 
-package org.apache.jena.riot.lang ;
+package org.apache.jena.riot.lang;
 
 import static org.apache.jena.riot.tokens.TokenType.*;
 
-import org.apache.jena.graph.Node ;
-import org.apache.jena.graph.NodeFactory ;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
 import org.apache.jena.riot.system.ParserProfile;
 import org.apache.jena.riot.system.PrefixMap;
 import org.apache.jena.riot.system.StreamRDF;
-import org.apache.jena.riot.tokens.Token ;
-import org.apache.jena.riot.tokens.TokenType ;
-import org.apache.jena.riot.tokens.Tokenizer ;
-import org.apache.jena.sparql.graph.NodeConst ;
+import org.apache.jena.riot.tokens.Token;
+import org.apache.jena.riot.tokens.TokenType;
+import org.apache.jena.riot.tokens.Tokenizer;
+import org.apache.jena.sparql.graph.NodeConst;
 
 /** The main engine for all things Turtle-ish (Turtle, TriG). */
 public abstract class LangTurtleBase extends LangBase {
     // See http://www.w3.org/TR/turtle/
     // Some predicates (if accepted)
-    protected final static String  KW_A           = "a" ;
-    protected final static String  KW_SAME_AS     = "=" ;
-    //protected final static String  KW_LOG_IMPLIES = "=>" ;
-    protected final static String  KW_TRUE        = "true" ;
-    protected final static String  KW_FALSE       = "false" ;
+    protected final static String  KW_A           = "a";
+    protected final static String  KW_SAME_AS     = "=";
+    //protected final static String  KW_LOG_IMPLIES = "=>";
+    protected final static String  KW_TRUE        = "true";
+    protected final static String  KW_FALSE       = "false";
 
-    protected final static boolean VERBOSE        = false ;
-    // protected final static boolean CHECKING = true ;
+    protected final static boolean VERBOSE        = false;
+    // protected final static boolean CHECKING = true;
     // Current graph - null for default graph
-    private Node                   currentGraph   = null ;
+    private Node                   currentGraph   = null;
 
     protected final PrefixMap prefixMap;
 
     protected final Node getCurrentGraph() {
-        return currentGraph ;
+        return currentGraph;
     }
 
     protected final void setCurrentGraph(Node graph) {
-        this.currentGraph = graph ;
+        this.currentGraph = graph;
     }
 
     protected LangTurtleBase(Tokenizer tokens, ParserProfile profile, StreamRDF dest) {
-        super(tokens, profile, dest) ;
+        super(tokens, profile, dest);
         prefixMap = profile.getPrefixMap();
     }
 
     @Override
     protected final void runParser() {
         while (moreTokens()) {
-            Token t = peekToken() ;
+            Token t = peekToken();
             if ( lookingAt(DIRECTIVE) ) {
-                directive() ; // @form.
-                continue ;
+                directive(); // @form.
+                continue;
             }
 
             if ( lookingAt(KEYWORD) ) {
                 if ( t.getImage().equalsIgnoreCase("PREFIX") || t.getImage().equalsIgnoreCase("BASE") ) {
-                    directiveKeyword() ;
-                    continue ;
+                    directiveKeyword();
+                    continue;
                 }
             }
 
-            oneTopLevelElement() ;
+            oneTopLevelElement();
 
             if ( lookingAt(EOF) )
-                break ;
+                break;
         }
     }
 
     // Do one top level item for the language.
-    protected abstract void oneTopLevelElement() ;
+    protected abstract void oneTopLevelElement();
 
     /**
      * Emit a triple - nodes have been checked as has legality of
      * node type in location.
      */
-    protected abstract void emit(Node subject, Node predicate, Node object) ;
+    protected abstract void emit(Node subject, Node predicate, Node object);
 
     protected final void directiveKeyword() {
-        Token t = peekToken() ;
-        String x = t.getImage() ;
-        nextToken() ;
+        Token t = peekToken();
+        String x = t.getImage();
+        nextToken();
 
         if ( x.equalsIgnoreCase("BASE") ) {
-            directiveBase() ;
-            return ;
+            directiveBase();
+            return;
         }
 
         if ( x.equalsIgnoreCase("PREFIX") ) {
-            directivePrefix() ;
-            return ;
+            directivePrefix();
+            return;
         }
-        exception(t, "Unrecognized keyword for directive: %s", x) ;
+        exception(t, "Unrecognized keyword for directive: %s", x);
     }
 
     protected final void directive() {
         // It's a directive ...
-        Token t = peekToken() ;
-        String x = t.getImage() ;
-        nextToken() ;
+        Token t = peekToken();
+        String x = t.getImage();
+        nextToken();
 
         if ( x.equals("base") ) {
-            directiveBase() ;
+            directiveBase();
             if ( isStrictMode() )
                 // The line number is probably one ahead due to the newline
-                expect("Base directive not terminated by a dot", DOT) ;
+                expect("Base directive not terminated by a dot", DOT);
             else
-                skipIf(DOT) ;
-            return ;
+                skipIf(DOT);
+            return;
         }
 
         if ( x.equals("prefix") ) {
-            directivePrefix() ;
+            directivePrefix();
             if ( isStrictMode() )
                 // The line number is probably one ahead due to the newline
-                expect("Prefix directive not terminated by a dot", DOT) ;
+                expect("Prefix directive not terminated by a dot", DOT);
             else
-                skipIf(DOT) ;
-            return ;
+                skipIf(DOT);
+            return;
         }
-        exception(t, "Unrecognized directive: %s", x) ;
+        exception(t, "Unrecognized directive: %s", x);
     }
 
     protected final void directivePrefix() {
         // Raw - unresolved prefix name.
         if ( !lookingAt(PREFIXED_NAME) )
-            exception(peekToken(), "PREFIX or @prefix requires a prefix (found '" + peekToken() + "')") ;
+            exception(peekToken(), "PREFIX or @prefix requires a prefix (found '" + peekToken() + "')");
         if ( peekToken().getImage2().length() != 0 )
-            exception(peekToken(), "PREFIX or @prefix requires a prefix with no suffix (found '" + peekToken() + "')") ;
-        String prefix = peekToken().getImage() ;
-        nextToken() ;
+            exception(peekToken(), "PREFIX or @prefix requires a prefix with no suffix (found '" + peekToken() + "')");
+        String prefix = peekToken().getImage();
+        nextToken();
         if ( !lookingAt(IRI) )
-            exception(peekToken(), "@prefix requires an IRI (found '" + peekToken() + "')") ;
-        String str = peekToken().getImage() ;
-        String iri = profile.resolveIRI(str, currLine, currCol) ;
-        prefixMap.add(prefix, iri) ;
-        emitPrefix(prefix, iri) ;
-        nextToken() ;
+            exception(peekToken(), "@prefix requires an IRI (found '" + peekToken() + "')");
+        String str = peekToken().getImage();
+        String iri = profile.resolveIRI(str, currLine, currCol);
+        prefixMap.add(prefix, iri);
+        emitPrefix(prefix, iri);
+        nextToken();
     }
 
     protected final void directiveBase() {
-        Token token = peekToken() ;
+        Token token = peekToken();
         if ( !lookingAt(IRI) )
-            exception(token, "BASE or @base requires an IRI (found '" + token + "')") ;
-        String str = token.getImage() ;
-        String baseIRI = profile.resolveIRI(str, currLine, currCol) ;
+            exception(token, "BASE or @base requires an IRI (found '" + token + "')");
+        String str = token.getImage();
+        String baseIRI = profile.resolveIRI(str, currLine, currCol);
         profile.setBaseIRI(baseIRI);
-        emitBase(baseIRI) ;
-        nextToken() ;
+        emitBase(baseIRI);
+        nextToken();
     }
 
     // Unlike many operations in this parser suite
@@ -175,17 +175,17 @@
 
         // TriplesSameSubject -> Term PropertyListNotEmpty
         if ( lookingAt(NODE) ) {
-            triples() ;
-            return ;
+            triples();
+            return;
         }
 
-        boolean maybeList = lookingAt(LPAREN) ;
+        boolean maybeList = lookingAt(LPAREN);
 
         // Turtle: TriplesSameSubject -> TriplesNode PropertyList?
         // TriG:   (blankNodePropertyList | collection) predicateObjectList? '.'
         //         labelOrSubject (wrappedGraph | predicateObjectList '.')
         if ( peekTriplesNodeCompound() ) {
-            Node n = triplesNodeCompound() ;
+            Node n = triplesNodeCompound();
 
             // May be followed by:
             // A predicateObject list
@@ -199,40 +199,40 @@
             // -- If strict turtle.
             if ( isStrictMode() && maybeList ) {
                 if ( peekPredicate() ) {
-                    predicateObjectList(n) ;
-                    expectEndOfTriples() ;
-                    return ;
+                    predicateObjectList(n);
+                    expectEndOfTriples();
+                    return;
                 }
                 exception(peekToken(), "Predicate/object required after (...) - Unexpected token : %s",
-                          peekToken()) ;
+                          peekToken());
             }
             // ---
             // If we allow top-level lists and [...].
             // Should check if () and [].
 
             if ( lookingAt(EOF) )
-                return ;
+                return;
             if ( lookingAt(DOT) ) {
-                nextToken() ;
-                return ;
+                nextToken();
+                return;
             }
 
             if ( peekPredicate() )
-                predicateObjectList(n) ;
-            expectEndOfTriples() ;
-            //exception(peekToken(), "Unexpected token : %s", peekToken()) ;
-            return ;
+                predicateObjectList(n);
+            expectEndOfTriples();
+            //exception(peekToken(), "Unexpected token : %s", peekToken());
+            return;
         }
 
         // <<>> subject position. Rule [10]
         if ( lookingAt(LT2) ) {
             Node subject = parseTripleTerm();
-            predicateObjectList(subject) ;
-            expectEndOfTriples() ;
+            predicateObjectList(subject);
+            expectEndOfTriples();
             return;
         }
 
-        exception(peekToken(), "Out of place: %s", peekToken()) ;
+        exception(peekToken(), "Out of place: %s", peekToken());
     }
 
     // Parse a << >> : RDF-star
@@ -258,7 +258,7 @@
         Node o = objectX();
 
         if ( ! lookingAt(GT2) )
-            exception(peekToken(), "Expected >>, found %s", peekToken().text()) ;
+            exception(peekToken(), "Expected >>, found %s", peekToken().text());
         nextToken();
 
         return profile.createTripleNode(s, p, o, token.getLine(), token.getColumn());
@@ -267,13 +267,13 @@
     private Node subjectX() {
         Node node = nodeX("subject");
         if ( node.isLiteral() )
-            exception(peekToken(), "Literal as subject in RDF-star triple") ;
-        return node ;
+            exception(peekToken(), "Literal as subject in RDF-star triple");
+        return node;
     }
 
     private Node objectX() {
         Node node = nodeX("object");
-        return node ;
+        return node;
     }
 
     // Does consume the token.
@@ -291,13 +291,13 @@
             nextToken();
             Token t = peekToken();
             if ( ! lookingAt(RBRACKET) )
-                exception(peekToken(), "Bad %s in RDF-star triple after [, expected ]", posnLabel, peekToken().text()) ;
+                exception(peekToken(), "Bad %s in RDF-star triple after [, expected ]", posnLabel, peekToken().text());
             nextToken();
-            return profile.createBlankNode(currentGraph, t.getLine(), t.getColumn()) ;
+            return profile.createBlankNode(currentGraph, t.getLine(), t.getColumn());
         }
 
         if ( ! lookingAt(NODE) )
-            exception(peekToken(), "Bad %s in RDF-star triple", posnLabel, peekToken().text()) ;
+            exception(peekToken(), "Bad %s in RDF-star triple", posnLabel, peekToken().text());
         Node node = node();
         nextToken();
         return node;
@@ -306,98 +306,98 @@
     // Must be at least one triple.
     protected final void triples() {
         // Looking at a node.
-        Node subject = node() ;
+        Node subject = node();
         if ( subject == null )
-            exception(peekToken(), "Not recognized: expected node: %s", peekToken().text()) ;
+            exception(peekToken(), "Not recognized: expected node: %s", peekToken().text());
 
-        nextToken() ;
-        predicateObjectList(subject) ;
-        expectEndOfTriples() ;
+        nextToken();
+        predicateObjectList(subject);
+        expectEndOfTriples();
     }
 
     // Differs between Turtle and TriG.
     // TriG, inside {} does not need the trailing DOT
-    protected abstract void expectEndOfTriples() ;
+    protected abstract void expectEndOfTriples();
 
     // The DOT is required by Turtle (strictly).
     // It is not in N3 and SPARQL.
 
     protected void expectEndOfTriplesTurtle() {
         if ( isStrictMode() )
-            expect("Triples not terminated by DOT", DOT) ;
+            expect("Triples not terminated by DOT", DOT);
         else
-            expectOrEOF("Triples not terminated by DOT", DOT) ;
+            expectOrEOF("Triples not terminated by DOT", DOT);
     }
 
     protected final void predicateObjectList(Node subject) {
-        predicateObjectItem(subject) ;
+        predicateObjectItem(subject);
 
         for (;;) {
             if ( !lookingAt(SEMICOLON) )
-                break ;
+                break;
             // predicatelist continues - move over all ";"
             while (lookingAt(SEMICOLON))
-                nextToken() ;
+                nextToken();
             if ( !peekPredicate() )
                 // Trailing (pointless) SEMICOLONs, no following
                 // predicate/object list.
-                break ;
-            predicateObjectItem(subject) ;
+                break;
+            predicateObjectItem(subject);
         }
     }
 
     protected final void predicateObjectItem(Node subject) {
-        Node predicate = predicate() ;
-        nextToken() ;
-        objectList(subject, predicate) ;
+        Node predicate = predicate();
+        nextToken();
+        objectList(subject, predicate);
     }
 
-    static protected final Node nodeSameAs     = NodeConst.nodeOwlSameAs ;
-    static protected final Node nodeLogImplies = NodeFactory.createURI("http://www.w3.org/2000/10/swap/log#implies") ;
+    static protected final Node nodeSameAs     = NodeConst.nodeOwlSameAs;
+    static protected final Node nodeLogImplies = NodeFactory.createURI("http://www.w3.org/2000/10/swap/log#implies");
 
     /** Get predicate - maybe null for "illegal" */
     protected final Node predicate() {
-        Token t = peekToken() ;
+        Token t = peekToken();
 
         if ( t.hasType(TokenType.KEYWORD) ) {
-            Token tErr = peekToken() ;
-            String image = peekToken().getImage() ;
+            Token tErr = peekToken();
+            String image = peekToken().getImage();
             if ( image.equals(KW_A) )
-                return NodeConst.nodeRDFType ;
+                return NodeConst.nodeRDFType;
             // N3-isms
             if ( !isStrictMode() && image.equals(KW_SAME_AS) )
-                return nodeSameAs ;
+                return nodeSameAs;
             // Relationship between two formulae in N3.
 //            if ( !strict && image.equals(KW_LOG_IMPLIES) )
 //                return log:implies;
-            exception(tErr, "Unrecognized keyword: " + image) ;
+            exception(tErr, "Unrecognized keyword: " + image);
         }
 
-        Node n = node() ;
+        Node n = node();
         if ( n == null || !n.isURI() )
-            exception(t, "Expected IRI for predicate: got: %s", t) ;
-        return n ;
+            exception(t, "Expected IRI for predicate: got: %s", t);
+        return n;
     }
 
     /** Check raw token to see if it might be a predicate */
     protected final boolean peekPredicate() {
         if ( lookingAt(TokenType.KEYWORD) ) {
-            String image = peekToken().getImage() ;
+            String image = peekToken().getImage();
             if ( image.equals(KW_A) )
-                return true ;
+                return true;
             if ( !isStrictMode() && image.equals(KW_SAME_AS) )
-                return true ;
+                return true;
 //            if ( !isStrictMode && image.equals(KW_LOG_IMPLIES) )
-//                return true ;
-            return false ;
+//                return true;
+            return false;
         }
         // if ( lookingAt(NODE) )
-        // return true ;
+        // return true;
         if ( lookingAt(TokenType.IRI) )
-            return true ;
+            return true;
         if ( lookingAt(TokenType.PREFIXED_NAME) )
-            return true ;
-        return false ;
+            return true;
+        return false;
     }
 
     /** Create a Node for the current token.
@@ -407,20 +407,20 @@
      */
     protected final Node node() {
         // Token to Node
-        Node n = tokenAsNode(peekToken()) ;
+        Node n = tokenAsNode(peekToken());
         if ( n == null )
-            return null ;
-        return n ;
+            return null;
+        return n;
     }
 
     protected final void objectList(Node subject, Node predicate) {
         for (;;) {
             // object ::=
-            Node object = triplesNode() ;
-            emitTriple(subject, predicate, object) ;
+            Node object = triplesNode();
+            emitTriple(subject, predicate, object);
             // RDF-star annotation syntax
             if ( lookingAt(L_ANN) ) {
-                Token tNext = nextToken() ;
+                Token tNext = nextToken();
                 if ( lookingAt(R_ANN) )
                     exception(tNext, "Empty annotation");
                 Node x = profile.createTripleNode(subject, predicate, object, currLine, currCol);
@@ -429,11 +429,11 @@
             }
 
             if ( !moreTokens() )
-                break ;
+                break;
             if ( !lookingAt(COMMA) )
-                break ;
+                break;
             // list continues - move over the ","
-            nextToken() ;
+            nextToken();
         }
     }
 
@@ -442,117 +442,117 @@
 
     protected final Node triplesNode() { // == [12] object in the grammar.
         if ( lookingAt(NODE) ) {
-            Node n = node() ;
-            nextToken() ;
-            return n ;
+            Node n = node();
+            nextToken();
+            return n;
         }
 
         // Special words.
         if ( lookingAt(TokenType.KEYWORD) ) {
-            Token tErr = peekToken() ;
+            Token tErr = peekToken();
             // Location independent node words
-            String image = peekToken().getImage() ;
-            nextToken() ;
+            String image = peekToken().getImage();
+            nextToken();
             if ( image.equals(KW_TRUE) )
-                return NodeConst.nodeTrue ;
+                return NodeConst.nodeTrue;
             if ( image.equals(KW_FALSE) )
-                return NodeConst.nodeFalse ;
+                return NodeConst.nodeFalse;
             if ( image.equals(KW_A) )
-                exception(tErr, "Keyword 'a' not legal at this point") ;
+                exception(tErr, "Keyword 'a' not legal at this point");
 
-            exception(tErr, "Unrecognized keyword: " + image) ;
+            exception(tErr, "Unrecognized keyword: " + image);
         }
 
         if ( lookingAt(LT2) )
             return parseTripleTerm();
 
-        return triplesNodeCompound() ;
+        return triplesNodeCompound();
     }
 
     protected final boolean peekTriplesNodeCompound() {
         if ( lookingAt(LBRACKET) )
-            return true ;
+            return true;
         if ( lookingAt(LBRACE) )
-            return true ;
+            return true;
         if ( lookingAt(LPAREN) )
-            return true ;
-        return false ;
+            return true;
+        return false;
     }
 
     protected final Node triplesNodeCompound() {
         if ( lookingAt(LBRACKET) )
-            return triplesBlankNode() ;
+            return triplesBlankNode();
         if ( lookingAt(LBRACE) )
-            return triplesFormula() ;
+            return triplesFormula();
         if ( lookingAt(LPAREN) )
-            return triplesList() ;
-        exception(peekToken(), "Unrecognized (expected an RDF Term): " + peekToken()) ;
-        return null ;
+            return triplesList();
+        exception(peekToken(), "Unrecognized (expected an RDF Term): " + peekToken());
+        return null;
     }
 
     protected final Node triplesBlankNode() {
-        Token t = nextToken() ; // Skip [
-        Node subject = profile.createBlankNode(currentGraph, t.getLine(), t.getColumn()) ;
-        triplesBlankNode(subject) ;
-        return subject ;
+        Token t = nextToken(); // Skip [
+        Node subject = profile.createBlankNode(currentGraph, t.getLine(), t.getColumn());
+        triplesBlankNode(subject);
+        return subject;
     }
 
     protected final void triplesBlankNode(Node subject) {
         if ( peekPredicate() )
-            predicateObjectList(subject) ;
-        expect("Triples not terminated properly in []-list", RBRACKET) ;
+            predicateObjectList(subject);
+        expect("Triples not terminated properly in []-list", RBRACKET);
         // Exit: after the ]
     }
 
     protected final Node triplesFormula() {
-        exception(peekToken(), "Not implemented (formulae, graph literals)") ;
-        return null ;
+        exception(peekToken(), "Not implemented (formulae, graph literals)");
+        return null;
     }
 
     protected final Node triplesList() {
-        nextToken() ;
-        Node lastCell = null ;
-        Node listHead = null ;
+        nextToken();
+        Node lastCell = null;
+        Node listHead = null;
 
-        startList() ;
+        startList();
 
         for (;;) {
             if ( eof() )
-                exception(peekToken(), "Unterminated list") ;
+                exception(peekToken(), "Unterminated list");
 
             if ( lookingAt(RPAREN) ) {
-                nextToken() ;
-                break ;
+                nextToken();
+                break;
             }
 
-            Token elementToken = peekToken() ;
+            Token elementToken = peekToken();
             // The value.
-            Node n = triplesNode() ;
+            Node n = triplesNode();
             if ( n == null )
-                exception(elementToken, "Malformed list") ;
+                exception(elementToken, "Malformed list");
 
             // Node for the list structure.
-            Node nextCell = profile.createBlankNode(currentGraph, elementToken.getLine(), elementToken.getColumn()) ;
+            Node nextCell = profile.createBlankNode(currentGraph, elementToken.getLine(), elementToken.getColumn());
             if ( listHead == null )
-                listHead = nextCell ;
+                listHead = nextCell;
             if ( lastCell != null )
-                emitTriple(lastCell, NodeConst.nodeRest, nextCell) ;
-            lastCell = nextCell ;
+                emitTriple(lastCell, NodeConst.nodeRest, nextCell);
+            lastCell = nextCell;
 
-            emitTriple(nextCell, NodeConst.nodeFirst, n) ;
+            emitTriple(nextCell, NodeConst.nodeFirst, n);
         }
         // On exit, just after the RPARENS
 
         if ( lastCell == null ) {
             // Simple ()
             finishList();
-            return NodeConst.nodeNil ;
+            return NodeConst.nodeNil;
         }
 
         // Finish list.
-        emitTriple(lastCell, NodeConst.nodeRest, NodeConst.nodeNil) ;
-        finishList() ;
-        return listHead ;
+        emitTriple(lastCell, NodeConst.nodeRest, NodeConst.nodeNil);
+        finishList();
+        return listHead;
     }
 
     // Signal start of a list
@@ -562,11 +562,11 @@
     protected void startList() {}
 
     protected final void emitTriple(Node subject, Node predicate, Node object) {
-        emit(subject, predicate, object) ;
+        emit(subject, predicate, object);
     }
 
     private final void emitPrefix(String prefix, String iriStr) {
-        dest.prefix(prefix, iriStr) ;
+        dest.prefix(prefix, iriStr);
     }
 
     private final void emitBase(String baseStr) {
@@ -574,6 +574,6 @@
     }
 
     protected final Node tokenAsNode(Token token) {
-        return profile.create(currentGraph, token) ;
+        return profile.create(currentGraph, token);
     }
 }
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/rowset/rw/RowSetWriterCSV.java b/jena-arq/src/main/java/org/apache/jena/riot/rowset/rw/RowSetWriterCSV.java
index 7887aed..a599822 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/rowset/rw/RowSetWriterCSV.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/rowset/rw/RowSetWriterCSV.java
@@ -26,15 +26,17 @@
 import org.apache.jena.atlas.io.AWriter;
 import org.apache.jena.atlas.io.IO;
 import org.apache.jena.graph.Node;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.riot.out.NodeToLabel;
 import org.apache.jena.riot.resultset.ResultSetLang;
 import org.apache.jena.riot.rowset.RowSetWriter;
 import org.apache.jena.riot.rowset.RowSetWriterFactory;
+import org.apache.jena.riot.system.SyntaxLabels;
 import org.apache.jena.sparql.core.Var;
 import org.apache.jena.sparql.engine.binding.Binding;
 import org.apache.jena.sparql.exec.RowSet;
 import org.apache.jena.sparql.resultset.ResultSetException;
 import org.apache.jena.sparql.util.Context;
-import org.apache.jena.sparql.util.NodeToLabelMap;
 
 public class RowSetWriterCSV implements RowSetWriter {
 
@@ -53,12 +55,12 @@
 
     @Override
     public void write(OutputStream out, RowSet resultSet, Context context) {
-        output(IO.wrapUTF8(out), resultSet);
+        output(IO.wrapUTF8(out), resultSet, context);
     }
 
     @Override
     public void write(Writer out, RowSet resultSet, Context context) {
-        output(IO.wrap(out), resultSet);
+        output(IO.wrap(out), resultSet, context);
     }
 
     @Override
@@ -79,9 +81,12 @@
         }
     }
 
-    private static void output(AWriter out, RowSet rowSet) {
+    private static void output(AWriter out, RowSet rowSet, Context context) {
         try {
-            NodeToLabelMap bnodes = new NodeToLabelMap();
+            boolean outputGraphBNodeLabels = (context != null) && context.isTrue(ARQ.outputGraphBNodeLabels);
+            NodeToLabel bnodes = outputGraphBNodeLabels
+                    ? SyntaxLabels.createNodeToLabelAsGiven()
+                    : SyntaxLabels.createNodeToLabel();
 
             String sep = null;
             List<Var> vars = rowSet.getResultVars();
@@ -116,15 +121,18 @@
         } finally { out.flush(); }
     }
 
-    private static void output(AWriter w, Node n, NodeToLabelMap bnodes) {
+    private static void output(AWriter w, Node n, NodeToLabel bnodes) {
         // String str = FmtUtils.stringForNode(n) ;
         String str = "?";
         if ( n.isLiteral() )
             str = n.getLiteralLexicalForm();
         else if ( n.isURI() )
             str = n.getURI();
-        else if ( n.isBlank() )
-            str = bnodes.asString(n);
+        else if ( n.isBlank() ) {
+            str = bnodes.get(null, n);
+            // Comes with leading "_:"
+            str = str.substring(2);
+        }
 
         str = csvSafe(str);
         w.write(str);
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/PrintingStreamRDF.java b/jena-arq/src/main/java/org/apache/jena/riot/system/PrintingStreamRDF.java
index bc369c5..9169e4d 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/PrintingStreamRDF.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/PrintingStreamRDF.java
@@ -20,17 +20,20 @@
 
 import java.io.OutputStream ;
 
+import org.apache.jena.atlas.io.AWriter;
 import org.apache.jena.atlas.io.IO;
+import org.apache.jena.graph.Triple;
 import org.apache.jena.riot.out.NodeFormatter;
 import org.apache.jena.riot.out.NodeFormatterTTL;
 import org.apache.jena.riot.writer.WriterStreamRDFPlain;
+import org.apache.jena.sparql.core.Quad;
 
 /**
- * A StreamRDF which displays the items sent to the stream. It is primarily for
- * development purposes.
+ * A StreamRDF which displays the items sent to the stream.
+ * It is primarily for development purposes.
  * <p>
  * The output is not a legal syntax. Do not consider this
- * format to be stable. It is "N-Quads with abbreviations".
+ * format to be stable.
  * <p>
  * Use via
  * <pre>
@@ -44,17 +47,33 @@
 
     public PrintingStreamRDF(OutputStream out) {
         super(IO.wrapUTF8(out));
+        // Always flush on each items.
+        // Too many points provide buffering or automatic newline
+        // handling  in different ways to get implicit consistent behaviour.
+        // This is a development helper.
+    }
+
+    public PrintingStreamRDF(AWriter out) {
+        super(out);
     }
 
     @Override
     protected NodeFormatter getFmt() { return pretty; }
 
+    // No prefix formatting.
+    private static void printDirectURI(AWriter out, String iriStr) {
+        out.print("<") ;
+        out.print(iriStr) ;
+        out.print(">") ;
+    }
+
     @Override
     public void base(String base) {
         out.print("BASE") ;
-        out.print("    ") ;
-        getFmt().formatURI(out, base);
+        out.print("  ") ;
+        printDirectURI(out, base);
         out.println();
+        flush();
         // Reset the formatter because of the new base URI.
         pretty = new NodeFormatterTTL(base, prefixMap);
     }
@@ -65,8 +84,25 @@
         out.print("  ") ;
         out.print(prefix) ;
         out.print(":  ") ;
-        getFmt().formatURI(out, iri);
+        printDirectURI(out, iri);
         out.println();
         prefixMap.add(prefix, iri);
+        flush();
+    }
+
+    @Override
+    public void triple(Triple triple) {
+        super.triple(triple);
+        flush();
+    }
+
+    @Override
+    public void quad(Quad quad) {
+        super.quad(quad);
+        flush();
+    }
+
+    public void flush() {
+        IO.flush(out) ;
     }
 }
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java b/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
index f1ffae0..2e0e7ee 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
@@ -22,7 +22,6 @@
 import static org.apache.jena.riot.RDFLanguages.NTRIPLES;
 import static org.apache.jena.riot.RDFLanguages.RDFJSON;
 import static org.apache.jena.riot.RDFLanguages.sameLang;
-import static org.apache.jena.riot.writer.WriterConst.PREFIX_IRI;
 
 import java.io.OutputStream;
 import java.io.Writer;
@@ -296,7 +295,7 @@
     private static void writeBaseNewStyle(IndentedWriter out, String base) {
         if (base != null) {
             out.print("BASE ");
-            out.pad(PREFIX_IRI);
+            out.pad(7);   // Align to possible prefixes. 7 is the length of "prefix "
             out.print("<");
             out.print(base);
             out.print(">");
@@ -307,7 +306,7 @@
     private static void writeBaseOldStyle(IndentedWriter out, String base) {
         if (base != null) {
             out.print("@base ");
-            out.pad(PREFIX_IRI);
+            out.pad(8);   // Align to possible prefixes. 8 is the length of "@prefix "
             out.print("<");
             out.print(base);
             out.print(">");
@@ -348,11 +347,11 @@
         writePrefix(out, prefix, uri, newStyle, 0);
     }
 
-    private static void writePrefix(IndentedWriter out, String prefix, String uri, boolean newStyle, int maxPrefixLenght) {
+    private static void writePrefix(IndentedWriter out, String prefix, String uri, boolean newStyle, int maxPrefixLength) {
         if (newStyle)
-            writePrefixNewStyle(out, prefix, uri, maxPrefixLenght);
+            writePrefixNewStyle(out, prefix, uri, maxPrefixLength);
         else
-            writePrefixOldStyle(out, prefix, uri, maxPrefixLenght);
+            writePrefixOldStyle(out, prefix, uri, maxPrefixLength);
     }
 
     /**
@@ -362,7 +361,7 @@
         out.print("PREFIX ");
         out.print(prefix);
         out.print(": ");
-        out.pad(9 + intent); // 9 e.q. length of "PREFIX" plus ": "
+        out.pad(9 + intent); // 9 is length of "PREFIX : "
         out.print("<");
         out.print(uri);
         out.print(">");
@@ -376,7 +375,7 @@
         out.print("@prefix ");
         out.print(prefix);
         out.print(": ");
-        out.pad(10 + intent); // 10 e.q. length of "@prefix" plus ": "
+        out.pad(10 + intent); // 10 is length of "@prefix : "
         out.print("<");
         out.print(uri);
         out.print(">");
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFLib.java b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFLib.java
index adefe02..2b3df62 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/StreamRDFLib.java
@@ -47,6 +47,12 @@
     public static StreamRDF print(OutputStream out)         { return new PrintingStreamRDF(out); }
 
     /**
+     * Create a {@link StreamRDF} that prints to an {@link AWriter}.
+     * This is debug output.
+     */
+    public static StreamRDF print(AWriter out)              { return new PrintingStreamRDF(out); }
+
+    /**
      * Create a {@link StreamRDF} that outputs to an {@link OutputStream}. It is important
      * to call {@link StreamRDF#start} and {@link StreamRDF#finish} because the output is
      * buffered.
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
index 9969b6f..0572035 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
@@ -32,14 +32,13 @@
 public class QueryEngineRegistry
 {
     List<QueryEngineFactory> factories = new ArrayList<>();
-    static { init(); }
 
     // Singleton
-    static QueryEngineRegistry registry = null;
+    private static QueryEngineRegistry registry;
+    static { init(); }
+
     static public QueryEngineRegistry get()
     {
-        if ( registry == null )
-            init();
         return registry;
     }
 
@@ -86,7 +85,7 @@
 
     public QueryEngineRegistry() { }
 
-    private static synchronized void init()
+    private static void init()
     {
         registry = new QueryEngineRegistry();
         registry.add(QueryEngineMain.getFactory());
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/modify/UpdateEngineRegistry.java b/jena-arq/src/main/java/org/apache/jena/sparql/modify/UpdateEngineRegistry.java
index 6ad8a68..d45eef5 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/modify/UpdateEngineRegistry.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/modify/UpdateEngineRegistry.java
@@ -27,20 +27,19 @@
 public class UpdateEngineRegistry
 {
     List<UpdateEngineFactory> factories = new ArrayList<>() ;
-    static { init() ; }
 
     // Singleton
-    static UpdateEngineRegistry registry = null ;
+    private static UpdateEngineRegistry registry ;
+    static { init() ; }
+
     static public UpdateEngineRegistry get()
     {
-        if ( registry == null )
-            init() ;
         return registry;
     }
 
     private UpdateEngineRegistry() { }
 
-    private static synchronized void init()
+    private static void init()
     {
         registry = new UpdateEngineRegistry() ;
         registry.add(UpdateEngineMain.getFactory()) ;
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
index 7c7b5f5..4c020e8 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
@@ -20,7 +20,7 @@
 
 import java.io.StringWriter ;
 
-/** IndentLineBuffer is a buffer that records an indent level 
+/** IndentLineBuffer is a buffer that records an indent level
  *  and uses that to insert a prefix at each line.
  *  It can also insert line numbers at the beginning of lines.
  */
@@ -29,15 +29,15 @@
 {
     StringWriter sw ;
     public IndentedLineBuffer() { this(false) ; }
-    
+
     public IndentedLineBuffer(boolean withLineNumbers)
     {
         super(new StringWriter(), withLineNumbers) ;
         sw = (StringWriter)super.out ;
     }
-    
+
     public StringBuffer getBuffer() { return sw.getBuffer(); }
-    
+
     public String asString() { return sw.toString() ; }
     @Override
     public String toString() { return asString() ; }
@@ -45,6 +45,6 @@
     // Names more usually used for a buffer.
     public void append(String fmt, Object... args) { printf(fmt, args) ; }
     public void append(char ch)  { print(ch) ;}
-    
+
     public void clear() { sw.getBuffer().setLength(0) ; }
 }
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
index 07f778b..8c0ff5c 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
@@ -17,14 +17,14 @@
  */
 
 package org.apache.jena.atlas.io;
-import static java.lang.String.format ;
+import static java.lang.String.format;
 
-import java.io.IOException ;
-import java.io.OutputStream ;
-import java.io.PrintStream ;
-import java.io.Writer ;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Writer;
 
-import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Closeable;
 
 /** A writer that records what the current indentation level is, and
  *  uses that to insert a prefix at each line.
@@ -33,45 +33,45 @@
 public class IndentedWriter extends AWriterBase implements AWriter, Closeable
 {
     /** Stdout wrapped in an IndentedWriter - no line numbers */
-    public static final IndentedWriter stdout = new IndentedWriter(System.out) ;
+    public static final IndentedWriter stdout = new IndentedWriter(System.out);
     /** Stderr wrapped in an IndentedWriter - no line numbers */
-    public static final IndentedWriter stderr = new IndentedWriter(System.err) ;
+    public static final IndentedWriter stderr = new IndentedWriter(System.err);
 
     static {
-        stdout.setFlushOnNewline(true) ;
-        stderr.setFlushOnNewline(true) ;
+        stdout.setFlushOnNewline(true);
+        stderr.setFlushOnNewline(true);
     }
 
     // Note cases:if (!flatMode)
     // 1/ incIndent - decIndent with no output should not cause any padding
     // 2/ newline() then no text, then finish should not cause a line number.
 
-    protected Writer out = null ;
+    protected Writer out = null;
 
-    protected static final int INDENT = 2 ;
+    protected static final int INDENT = 2;
 
     // Configuration.
-    protected int unitIndent = INDENT ;
-    private char padChar = ' ' ;
-    private String padString = null ;
-    private String linePrefix = null ;
-    protected boolean lineNumbers = false ;
-    protected boolean flatMode = false ;
-    private boolean flushOnNewline = false ;
+    protected int unitIndent = INDENT;
+    private char padChar = ' ';
+    private String padString = null;
+    private String linePrefix = null;
+    protected boolean lineNumbers = false;
+    protected boolean flatMode = false;
+    private boolean flushOnNewline = false;
 
     // Internal state.
-    protected boolean startingNewLine = true ;
-    private String endOfLineMarker = null ;
-    protected int currentIndent = 0 ;
-    protected int column = 0 ;
-    protected int row = 1 ;
+    protected boolean startingNewLine = true;
+    private String endOfLineMarker = null;
+    protected int currentIndent = 0;
+    protected int column = 0;
+    protected int row = 1;
 
     /** Construct a UTF8 IndentedWriter around an OutputStream */
-    public IndentedWriter(OutputStream outStream) { this(outStream, false) ; }
+    public IndentedWriter(OutputStream outStream) { this(outStream, false); }
 
     /** Construct a UTF8 IndentedWriter around an OutputStream */
     public IndentedWriter(OutputStream outStream, boolean withLineNumbers) {
-        this(makeWriter(outStream), withLineNumbers) ;
+        this(makeWriter(outStream), withLineNumbers);
     }
 
     /** Create an independent copy of the {@code IndentedWriter}.
@@ -100,7 +100,7 @@
         return clone(this);
     }
     private static Writer makeWriter(OutputStream out) {
-        return IO.asBufferedUTF8(out) ;
+        return IO.asBufferedUTF8(out);
     }
 
     /** Using Writers directly is discouraged */
@@ -110,115 +110,140 @@
 
     /** Using Writers directly is discouraged */
     protected IndentedWriter(Writer writer, boolean withLineNumbers) {
-        out = writer ;
-        lineNumbers = withLineNumbers ;
-        startingNewLine = true ;
+        out = writer;
+        lineNumbers = withLineNumbers;
+        startingNewLine = true;
     }
 
+    protected IndentedWriter rtnObject() { return this; }
+
     @Override
     public void print(String str) {
         if ( str == null )
-            str = "null" ;
+            str = "null";
         if ( false ) {
             // Don't check for embedded newlines.
-            write$(str) ;
-            return ;
+            write$(str);
+            return;
         }
-        for ( int i = 0 ; i < str.length() ; i++ )
-            printOneChar(str.charAt(i)) ;
+        for ( int i = 0; i < str.length(); i++ )
+            printOneChar(str.charAt(i));
     }
 
     @Override
     public void printf(String formatStr, Object... args) {
-        print(format(formatStr, args)) ;
+        print(format(formatStr, args));
     }
 
     @Override
-    public void print(char ch)      { printOneChar(ch) ; }
+    public void print(char ch)      { printOneChar(ch); }
     public void print(Object obj)   { print(String.valueOf(obj)); }
 
     @Override
-    public void println(String str) { print(str) ; newline() ; }
-    public void println(char ch)    { print(ch) ; newline() ; }
+    public void println(String str) { print(str); newline(); }
+    public void println(char ch)    { print(ch); newline(); }
     public void println(Object obj) { print(String.valueOf(obj)); newline(); }
 
     @Override
-    public void println() { newline() ; }
+    public void println() { newline(); }
 
     @Override
     public void print(char[] cbuf) {
         for ( char aCbuf : cbuf ) {
-            printOneChar(aCbuf) ;
+            printOneChar(aCbuf);
         }
     }
 
     /** Print a string N times */
     public void print(String s, int n) {
-        for ( int i = 0 ; i < n ; i++ )
-            print(s) ;
+        for ( int i = 0; i < n; i++ )
+            print(s);
     }
 
     /** Print a char N times */
     public void print(char ch, int n) {
-        lineStart() ;
-        for ( int i = 0 ; i < n ; i++ )
-            printOneChar(ch) ;
+        lineStart();
+        for ( int i = 0; i < n; i++ )
+            printOneChar(ch);
     }
 
-    private char lastChar = '\0' ;
+    private char lastChar = '\0';
 
     // Worker
     private void printOneChar(char ch) {
         // Turn \r\n into a single newline call.
         // Assumes we don't get \r\r\n etc
         if ( ch == '\n' && lastChar == '\r' ) {
-            lastChar = ch ;
-            return ;
+            lastChar = ch;
+            return;
         }
 
-        lineStart() ;
-        lastChar = ch ;
+        lineStart();
+        lastChar = ch;
 
         // newline
         if ( ch == '\n' || ch == '\r' ) {
-            newline() ;
-            return ;
+            newline();
+            return;
         }
-        write$(ch) ;
-        column += 1 ;
+        write$(ch);
+        column += 1;
     }
 
     private void write$(char ch)
-    { try { out.write(ch) ; } catch (IOException ex) { IO.exception(ex); } }
+    { try { out.write(ch); } catch (IOException ex) { IO.exception(ex); } }
 
     private void write$(String s)
-    { try { out.write(s) ; } catch (IOException ex) { IO.exception(ex); } }
+    { try { out.write(s); } catch (IOException ex) { IO.exception(ex); } }
 
     public void newline() {
-        lineStart() ;
+        lineStart();
 
         if ( endOfLineMarker != null )
-            print(endOfLineMarker) ;
+            print(endOfLineMarker);
         if ( !flatMode )
-            write$('\n') ;
-        startingNewLine = true ;
-        row++ ;
-        column = 0 ;
+            write$('\n');
+        startingNewLine = true;
+        row++;
+        column = 0;
         // Note that PrintWriters do not autoflush by default
         // so if layered over a PrintWriter, need to flush that as well.
         if ( flushOnNewline )
-            flush() ;
+            flush();
     }
 
-    private boolean atStartOfLine() { return column <= currentIndent ; }
+    private boolean atStartOfLine() { return column <= currentIndent; }
 
     public void ensureStartOfLine() {
         if ( !atStartOfLine() )
-            newline() ;
+            newline();
+    }
+
+    public boolean atLineStart()        { return startingNewLine; }
+
+    // A line is prefix?number?content.
+    private void lineStart() {
+        if ( flatMode ) {
+            if ( startingNewLine && row > 1 )
+                // Space between each line.
+                write$(' ');
+            startingNewLine = false;
+            return;
+        }
+
+        // Need to do this at line start, not at the previous line end
+        // otherwise a final blank line will have a prefix and line number.
+        if ( startingNewLine ) {
+            if ( linePrefix != null )
+                write$(linePrefix);
+            insertLineNumber();
+        }
+        padInternal();
+        startingNewLine = false;
     }
 
     @Override
-    public void close() { IO.close(out) ; }
+    public void close() { IO.close(out); }
 
     @Override
     public void flush() { IO.flush(out); }
@@ -226,15 +251,15 @@
     /** Pad to the indent (if we are before it) */
     public void pad() {
         if ( startingNewLine && currentIndent > 0 )
-            lineStart() ;
-        padInternal() ;
+            lineStart();
+        padInternal();
     }
 
     /** Pad to a given number of columns EXCLUDING the indent.
      *
      * @param col Column number (first column is 1).
      */
-    public void pad(int col) { pad(col, false) ; }
+    public void pad(int col) { pad(col, false); }
 
     /** Pad to a given number of columns maybe including the indent.
      *
@@ -244,151 +269,163 @@
     public void pad(int col, boolean absoluteColumn) {
         // Make absolute
         if ( !absoluteColumn )
-            col = col + currentIndent ;
-        int spaces = col - column ;
-        for ( int i = 0 ; i < spaces ; i++ ) {
-            write$(' ') ;        // Always a space.
-            column++ ;
+            col = col + currentIndent;
+        int spaces = col - column;
+        for ( int i = 0; i < spaces; i++ ) {
+            write$(' ');        // Always a space.
+            column++;
         }
     }
 
     private void padInternal() {
         if ( padString == null ) {
-            for ( int i = column ; i < currentIndent ; i++ ) {
-                write$(padChar) ;
-                column++ ;
+            for ( int i = column; i < currentIndent; i++ ) {
+                write$(padChar);
+                column++;
             }
         } else {
-            for ( int i = column ; i < currentIndent ; i += padString.length() ) {
-                write$(padString) ;
-                column += padString.length() ;
+            for ( int i = column; i < currentIndent; i += padString.length() ) {
+                write$(padString);
+                column += padString.length();
             }
         }
     }
 
     /** Get row/line (counts from 1) */
-    public int getRow() { return row ; }
+    public int getRow() { return row; }
     /** Get the absolute column.
      *  This is the location where the next character on the line will be printed.
      *  The IndentedWriter may not yet have padded to this place.
      */
     public int getCol() {
         if ( currentIndent > column )
-            return currentIndent ;
-        return column ;
+            return currentIndent;
+        return column;
     }
 
-    /** Get indent from the left hand edge */
-    public int getAbsoluteIndent()       { return currentIndent ; }
-    /** Set indent from the left hand edge */
-    public void setAbsoluteIndent(int x) { currentIndent = x ; }
+    public void incIndent() { incIndent(unitIndent); }
+
+    public void incIndent(int x) {
+        currentIndent += x;
+    }
+
+    public void decIndent() { decIndent(unitIndent); }
+
+    public void decIndent(int x) {
+        currentIndent -= x;
+    }
 
     /** Position past current indent */
     public int getCurrentOffset() {
-        int x = getCol() - getAbsoluteIndent() ;
+        int x = getCol() - getAbsoluteIndent();
         if ( x >= 0 )
-            return x ;
+            return x;
         // At start of line somehow.
-        return 0 ;
+        return 0;
     }
 
+    /** Get indent from the left hand edge */
+    public int getAbsoluteIndent()       { return currentIndent; }
+
+    /** Set indent from the left hand edge. Returns {@code this}. */
+    public IndentedWriter setAbsoluteIndent(int x) { currentIndent = x; return rtnObject(); }
+
     public boolean hasLineNumbers() {
-        return lineNumbers ;
+        return lineNumbers;
     }
 
-    public void setLineNumbers(boolean lineNumbers) {
-        this.lineNumbers = lineNumbers ;
+    public IndentedWriter setLineNumbers(boolean lineNumbers) {
+        this.lineNumbers = lineNumbers;
+        return rtnObject();
     }
 
-    public String getEndOfLineMarker()              { return endOfLineMarker ; }
+    public String getEndOfLineMarker()              { return endOfLineMarker; }
 
     /** Set the marker included at end of line - set to null for "none".  Usually used for debugging. */
-    public void setEndOfLineMarker(String marker)   { endOfLineMarker = marker ; }
+    public IndentedWriter setEndOfLineMarker(String marker) {
+        endOfLineMarker = marker;
+        return rtnObject();
+    }
 
     /** Flat mode - print without NL, for a more compact representation*/
-    public boolean inFlatMode()                     { return flatMode ; }
+    public boolean inFlatMode()                     { return flatMode; }
     /** Flat mode - print without NL, for a more compact representation*/
-    public void setFlatMode(boolean flatMode)       { this.flatMode = flatMode ; }
+    public IndentedWriter setFlatMode(boolean flatMode) {
+        this.flatMode = flatMode;
+        return rtnObject();
+    }
 
     /** Flush on newline **/
     public boolean getFlushOnNewline()              { return flushOnNewline; }
+
     /** Flush on newline in this code.
      * This is set for {@link IndentedWriter#stdout} and {@link IndentedWriter#stderr}
      * but not by default otherwise. The underlying output, if it is a {@link PrintStream}
      * may also have a flush on newline as well (e.g {@link System#out}).
      */
-    public void setFlushOnNewline(boolean flushOnNewline)
-    { this.flushOnNewline = flushOnNewline; }
+    public IndentedWriter setFlushOnNewline(boolean flushOnNewline) {
+        this.flushOnNewline = flushOnNewline;
+        return rtnObject();
+    }
 
-    public char getPadChar()                        { return padChar ; }
-    public void setPadChar(char ch)                 { this.padChar  = ch ; }
-    public String getPadString()                    { return padString ; }
-    public void setPadString(String str)            { this.padString = str ; unitIndent = str.length(); }
+    public char getPadChar()                        { return padChar; }
+
+    public IndentedWriter setPadChar(char ch) {
+        this.padChar = ch;
+        return rtnObject();
+    }
+
+    public String getPadString()                    { return padString; }
+
+    public IndentedWriter setPadString(String str) {
+        this.padString = str;
+        this.unitIndent = str.length();
+        return rtnObject();
+    }
 
     /** Initial string printed at the start of each line : defaults to no string. */
-    public String getLinePrefix()                   { return linePrefix  ; }
+    public String getLinePrefix() {
+        return linePrefix;
+    }
+
     /** Set the initial string printed at the start of each line. */
-    public void setLinePrefix(String str)           { this.linePrefix = str ; }
-
-    public void incIndent() { incIndent(unitIndent) ; }
-
-    public void incIndent(int x) {
-        currentIndent += x ;
+    public IndentedWriter setLinePrefix(String str) {
+        this.linePrefix = str;
+        return rtnObject();
     }
 
-    public void decIndent() { decIndent(unitIndent) ; }
+    public int  getUnitIndent()         { return unitIndent; }
 
-    public void decIndent(int x) {
-        currentIndent -= x ;
+    public IndentedWriter setUnitIndent(int x) {
+        unitIndent = x;
+        return rtnObject();
     }
 
-    public void setUnitIndent(int x)    { unitIndent = x ; }
-    public int  getUnitIndent()         { return unitIndent ; }
-    public boolean atLineStart()        { return startingNewLine ; }
-
-    // A line is prefix?number?content.
-    private void lineStart() {
-        if ( flatMode ) {
-            if ( startingNewLine && row > 1 )
-                // Space between each line.
-                write$(' ') ;
-            startingNewLine = false ;
-            return ;
-        }
-
-        // Need to do its just before we append anything, not after a NL,
-        // so that a final blank does not cause a prefix or line number.
-        if ( startingNewLine ) {
-            if ( linePrefix != null )
-                write$(linePrefix) ;
-            insertLineNumber() ;
-        }
-        padInternal() ;
-        startingNewLine = false ;
-    }
-
-    private int widthLineNumber = 3 ;
+    private int widthLineNumber = 3;
 
     /** Width of the number field */
-    public int getNumberWidth() { return widthLineNumber ; }
+    public int getNumberWidth() { return widthLineNumber; }
 
     /** Set the width of the number field.
      * There is also a single space after the number not included in this setting.
      */
-    public void setNumberWidth(int widthOfNumbers) { widthLineNumber = widthOfNumbers ; }
+    public IndentedWriter setNumberWidth(int widthOfNumbers) {
+        widthLineNumber = widthOfNumbers;
+        return rtnObject();
+    }
 
     private void insertLineNumber() {
         if ( !lineNumbers )
-            return ;
-        String s = Integer.toString(row) ;
-        for ( int i = 0 ; i < widthLineNumber - s.length() ; i++ )
-            write$(' ') ;
-        write$(s) ;
-        write$(' ') ;
+            return;
+        String s = Integer.toString(row);
+        for ( int i = 0; i < widthLineNumber - s.length(); i++ )
+            write$(' ');
+        write$(s);
+        write$(' ');
     }
 
     @Override
     public String toString() {
-        return String.format("Indent = %d : Row = %d : Col = %d", currentIndent, row, column) ;
+        return String.format("Indent = %d : Row = %d : Col = %d", currentIndent, row, column);
     }
 }
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java b/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
index 100ec6f..d60a901 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
@@ -18,80 +18,100 @@
 
 package org.apache.jena.atlas.io;
 
-import java.io.BufferedWriter ;
-import java.io.IOException ;
-import java.io.Writer ;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.Writer;
 
-import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Closeable;
 
 /** A Writer, without the checked exceptions. */
 
 public class Writer2 extends AWriterBase implements AWriter, Closeable
 {
-    protected final Writer writer ;
+    protected final Writer writer;
 
-    public static Writer2 wrap(Writer writer)
-    {
+    public static Writer2 wrapNoBuffer(Writer writer) {
+        return new Writer2(writer);
+    }
+
+    public static Writer2 wrap(Writer writer) {
         if ( writer instanceof BufferedWriter )
-            return new Writer2(writer) ;
+            return new Writer2(writer);
         if ( writer instanceof BufferingWriter )
-            return new Writer2(writer) ;
-        
-        writer = new BufferingWriter(writer) ;
-        return new Writer2(writer) ;
-    }
-    
-    protected Writer2(Writer writer) { this.writer = writer ; }
+            return new Writer2(writer);
 
-    @Override
-    public void print(char ch)
-    { 
-        try { writer.write(ch) ; } catch (IOException ex) { IO.exception(ex) ; }
+        writer = new BufferingWriter(writer);
+        return new Writer2(writer);
+    }
+
+    protected Writer2(Writer writer) {
+        this.writer = writer;
     }
 
     @Override
-    public void print(String string)
-    { 
-        try { writer.write(string) ; } catch (IOException ex) { IO.exception(ex) ; }
+    public void print(char ch) {
+        try {
+            writer.write(ch);
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
     }
 
     @Override
-    public void print(char[] cbuf)
-    {
-        try { writer.write(cbuf) ; } catch (IOException ex) { IO.exception(ex) ; }
+    public void print(String string) {
+        try {
+            writer.write(string);
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
     }
 
     @Override
-    public void flush()
-    {
-        try { writer.flush() ; } catch (IOException ex) { IO.exception(ex) ; }
+    public void print(char[] cbuf) {
+        try {
+            writer.write(cbuf);
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
     }
 
     @Override
-    public void close()
-    {
-        try { writer.close() ; } catch (IOException ex) { IO.exception(ex) ; }
+    public void flush() {
+        try {
+            writer.flush();
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
     }
 
     @Override
-    public void printf(String fmt, Object... args)
-    {
-        print(String.format(fmt, args)) ;
+    public void close() {
+        try {
+            writer.close();
+        } catch (IOException ex) {
+            IO.exception(ex);
+        }
     }
 
     @Override
-    public void println(String obj)
-    {
-        print(obj) ; print("\n") ;
+    public void printf(String fmt, Object...args) {
+        print(String.format(fmt, args));
     }
 
     @Override
-    public void println()
-    {
-        print("\n") ;
+    public void println(String obj) {
+        print(obj);
+        print("\n");
     }
-    
+
     @Override
-    public String toString() { return writer.toString() ; }
+    public void println() {
+        print("\n");
+    }
+
+    @Override
+    public String toString() {
+        return writer.toString();
+    }
 }
 
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
index dc9c687..addaafa 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
@@ -46,7 +46,7 @@
         @SuppressWarnings("unchecked")
         Caffeine<K,V> builder = (Caffeine<K,V>)Caffeine.newBuilder()
             .maximumSize(size)
-            .initialCapacity(size/2)
+            .initialCapacity(size/4)
             // Eviction immediately using the caller thread.
             .executor(c->c.run());
 
diff --git a/jena-cmds/src/main/java/arq/query.java b/jena-cmds/src/main/java/arq/query.java
index c827fcd..e3e7a6c 100644
--- a/jena-cmds/src/main/java/arq/query.java
+++ b/jena-cmds/src/main/java/arq/query.java
@@ -153,7 +153,7 @@
         // Warm up.
         for ( int i = 0 ; i < warmupCount ; i++ )
             // Include the results format so that is warmed up as well.
-            queryExec(false, modResults.getResultsFormat(), NullPrintStream.NULL_PRINT_STREAM) ;
+            queryExec(false, modResults.getResultsFormat(), NullPrintStream.INSTANCE) ;
 
         for ( int i = 0 ; i < repeatCount ; i++ )
             queryExec(modTime.timingEnabled(),  modResults.getResultsFormat(), System.out) ;
diff --git a/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdExt.java b/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdExt.java
index 373d093..3907754 100644
--- a/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdExt.java
+++ b/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdExt.java
@@ -38,7 +38,7 @@
     @Before
     public void beforeTest() {
         stderr = System.err;
-        System.setErr(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM));
+        System.setErr(new PrintStream(NullOutputStream.INSTANCE));
     }
 
     @After
diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/ARPErrorNumbers.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/ARPErrorNumbers.java
index 1074320..6a48c33 100644
--- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/ARPErrorNumbers.java
+++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/ARPErrorNumbers.java
@@ -73,7 +73,7 @@
      * see LanguageTagCodes#LT_EXTRA
      */
 
-    public int IGN_PRIVATE_XMLLANG = 1;
+    //public int IGN_PRIVATE_XMLLANG = 1;
 
     /**
      Indicates that somewhere, other than in an XML Literal
diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ARPLocation.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ARPLocation.java
index 02954a7..9370028 100644
--- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ARPLocation.java
+++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ARPLocation.java
@@ -49,6 +49,19 @@
         "line " + endLine + " in '"
         + inputName + "'";
     }
+
+    public String locationStr() {
+        int line = getLineNumber();
+        int col = getColumnNumber();
+        if ( col == -1 && line == -1 )
+            return "[?, ?]";
+        if ( col == -1 && line != -1 )
+            return String.format("[line: %d]", line);
+        if ( col != -1 && line == -1 )
+            return String.format("[col: %d]", col);
+        return String.format("[line: %d, col: %d]", line, col);
+    }
+
     @Override
     public String getSystemId() {
         return inputName;
diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ElementLexer.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ElementLexer.java
index d1f88cb..5575002 100644
--- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ElementLexer.java
+++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ElementLexer.java
@@ -22,7 +22,7 @@
 import org.xml.sax.SAXParseException;
 
 public class ElementLexer extends QNameLexer  {
-    
+
     final private String uri;
     final private String localName;
     final private String qname;
@@ -39,18 +39,18 @@
         goodMatch = (good&match) != 0;
         // Note: this.bad excludes good.
         badMatch = (this.bad&match) != 0;
-        
+
         if ((!(goodMatch||badMatch))&&(this.bad&E_RDF)==E_RDF) {
             if (rdfns.equals(uri)) {
                 if (isMemberProperty(localName)){
                     if (report_1)
-                    frame.warning(t,WARN_RDF_NN_AS_TYPE,
-                            qname + " is being used on a typed node.");
+                        frame.warning(t,WARN_RDF_NN_AS_TYPE,
+                                      qname + " is being used on a typed node.");
                 } else if (!isKnownNonMemberRDFProperty(localName)) {
-                frame.warning(t,WARN_UNKNOWN_RDF_ELEMENT,
-                        qname + " is not a recognized RDF property or type.");
-                
-            }
+                    frame.warning(t,WARN_UNKNOWN_RDF_ELEMENT,
+                                  qname + " is not a recognized RDF property or type.");
+
+                }
             }
         }
     }
@@ -64,7 +64,7 @@
                 r==E_LI?ERR_LI_AS_TYPE:
                 ERR_BAD_RDF_ELEMENT,
                 getQName() + " is not allowed as an element tag here.");
-        
+
     }
     @Override
     void deprecatedAttribute(Taint me,int r) throws SAXParseException {
@@ -85,7 +85,7 @@
     @Override
     void bagIDAttribute(Taint taintMe, int rslt) throws SAXParseException {
         error(taintMe,rslt);
-        
+
     }
 
 }
diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ParserSupport.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ParserSupport.java
index ec097a4..edec976 100644
--- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ParserSupport.java
+++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/impl/ParserSupport.java
@@ -60,11 +60,13 @@
 			if (prev != null) {
 				arp.warning(taintMe,
 					WARN_REDEFINITION_OF_ID,
-					"Redefinition of ID: " + str);
-				arp.warning(taintMe,
-					WARN_REDEFINITION_OF_ID,
-					prev,
-					"Previous definition of '" + str + "'.");
+					// RIOT format [line: 22, col: 31]
+					"Redefinition of ID: '" + str +"' defined at "+prev.locationStr());
+				// ARP used to produce two warnings.
+//				arp.warning(taintMe,
+//					WARN_REDEFINITION_OF_ID,
+//					prev,
+//					"Previous definition of '" + str + "'.");
 			} else {
 				idsUsedForBase.put(str, arp.location());
 				arp.idsUsedCount++;
diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/states/Frame.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/states/Frame.java
index f49a1df..f7584d2 100644
--- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/states/Frame.java
+++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmlinput/states/Frame.java
@@ -112,11 +112,10 @@
                                 "Unqualified property attributes are not allowed. Property treated as a relative URI.");
                     }
                     if (rdfns.equals(uri) && !QNameLexer.isKnownRDFProperty(lName)) {
-                        warning(
-                                        pred,
-                                        WARN_UNKNOWN_RDF_ATTRIBUTE,
-                                        atts.getQName(i)
-                                                + " is not a recognized RDF property or type.");
+                        warning(pred,
+                                WARN_UNKNOWN_RDF_ATTRIBUTE,
+                                atts.getQName(i)
+                                + " is not a recognized RDF property.");
                     }
                     ((HasSubjectFrameI) this).aPredAndObj(pred, new ARPString(
                             this, atts.getValue(i), x));
diff --git a/jena-core/src/main/java/org/apache/jena/util/JenaXMLInput.java b/jena-core/src/main/java/org/apache/jena/util/JenaXMLInput.java
index 6d7f579..d9f1578 100644
--- a/jena-core/src/main/java/org/apache/jena/util/JenaXMLInput.java
+++ b/jena-core/src/main/java/org/apache/jena/util/JenaXMLInput.java
@@ -37,9 +37,13 @@
 /**
  * Create XML input methods.
  * <p>
- * External DTD and entity processing is disabled to prevent
- * <a href="https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing">XXE Processing</a>
- * problems.
+ * External DTDs and remote entity processing is disabled to prevent XXE attacks.
+ * <br/>
+ * <a href="https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing">XXE Processing Problems</a>
+ * <p>
+ * For advice in preventing these attacks, see
+ * <a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html">XML External Entity Prevention Cheat Sheet</a>
+ * which has a <a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java">Java section</a>.
  */
 public class JenaXMLInput {
 
@@ -48,22 +52,37 @@
     private static SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
 
     public static XMLReader createXMLReader() throws ParserConfigurationException, SAXException {
-            SAXParser saxParser = saxParserFactory.newSAXParser();
-            XMLReader xmlreader = saxParser.getXMLReader();
+        /*
+         * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader
+         * ----
+         * XMLReader
+         *
+         *    To protect a Java org.xml.sax.XMLReader from XXE, do this:
+         *
+         *    XMLReader reader = XMLReaderFactory.createXMLReader();
+         *    reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+         *    // This may not be strictly required as DTDs shouldn't be allowed at all, per previous line.
+         *    reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+         *    reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+         *    reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+         */
 
-            // XXE : disable all DTD processing.
-            // Effect: RiotException if a DTD is found.
-            // However, OWL WG test files, and others, have internal entity
-            // declarations in internal DTD subset ("the "[ ]"in a DOCTYPE).
-            // xmlreader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-            // instead, silently ignore external DTDs.
+        SAXParser saxParser = saxParserFactory.newSAXParser();
+        XMLReader xmlreader = saxParser.getXMLReader();
 
-            // Always disable remote DTDs (silently ignore if DTDs are allowed at all)
-            xmlreader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
-            // and ignore external entities (silently ignore)
-            xmlreader.setFeature("http://xml.org/sax/features/external-general-entities", false);
-            xmlreader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-            return xmlreader;
+        // XXE : disable all DTD processing.
+        // Effect: RiotException if a DTD is found.
+        // However, OWL WG test files, and others, have internal entity
+        // declarations in internal DTD subset ("the "[ ]"in a DOCTYPE).
+        // xmlreader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        // instead, silently ignore external DTDs.
+
+        // Always disable remote DTDs (silently ignore if DTDs are allowed at all)
+        xmlreader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        // and ignore external entities (silently ignore)
+        xmlreader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        xmlreader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+        return xmlreader;
     }
 
     // ---- StAX
@@ -72,15 +91,38 @@
      * Initialize an XMLInputFactory to jena settings.
      */
     public static void initXMLInputFactory(XMLInputFactory xf) {
+        /*
+         * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+         * ---
+         *     // This disables DTDs entirely for that factory
+         *     xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+         *
+         * or if you can't completely disable DTDs:
+         *
+         *     // This causes XMLStreamException to be thrown if external DTDs are accessed.
+         *     xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+         *     // disable external entities
+         *     xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
+         */
+
+        String name = xf.getClass().getName();
+        boolean isWoodstox = name.startsWith("com.ctc.wstx.stax.");
+        boolean isJDK = name.contains("sun.xml.internal");
+        boolean isXerces = name.startsWith("org.apache.xerces");
+
         // This disables DTDs entirely for the factory.
-        // All DTDs are silently ignored; takes precedence over ACCESS_EXTERNAL_DTD
+        // DTDs are silently ignored except for xmlEventReader.nextTag() which throws an exception on a "DTD" event.
+        // Code can peek and skip the DTD.
+        // This takes precedence over ACCESS_EXTERNAL_DTD
     	setXMLInputFactoryProperty(xf, XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
 
         // disable external entities (silently ignore)
         setXMLInputFactoryProperty(xf, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
 
+        // Not supported by Woodstox. IS_SUPPORTING_EXTERNAL_ENTITIES = false is enough.
         // Disable external DTDs (files and HTTP) - errors unless SUPPORT_DTD is false.
-        setXMLInputFactoryProperty(xf, XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        if ( ! isWoodstox )
+            setXMLInputFactoryProperty(xf, XMLConstants.ACCESS_EXTERNAL_DTD, "");
     }
 
     /**
@@ -115,15 +157,21 @@
         return factory;
     }
 
-//    // For reference : jdom:
+    // https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxbuilder
+    // For reference : org.jdom2.input
 //    // ---- SAXBuilder
 //    public static SAXBuilder newSAXBuilder() throws ParserConfigurationException {
 //        SAXBuilder builder = new SAXBuilder();
-//        //builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
-//        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false;)
+//
+//        // Completely disable
+//        builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
+//
+//        // Or disable external entities and entity expansion:
+//        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
 //        builder.setFeature("http://xml.org/sax/features/external-general-entities", false);
 //        builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
 //        builder.setExpandEntities(false);
+//
 //        return builder;
 //    }
 }
diff --git a/jena-extras/jena-commonsrdf/pom.xml b/jena-extras/jena-commonsrdf/pom.xml
index 25702c6..c21c120 100644
--- a/jena-extras/jena-commonsrdf/pom.xml
+++ b/jena-extras/jena-commonsrdf/pom.xml
@@ -54,7 +54,7 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-rdf-api</artifactId>
-      <version>${ver.commonsrdf}</version>
+      <version>${ver.commons-rdf}</version>
       <classifier>tests</classifier>
       <scope>test</scope>
     </dependency>
@@ -63,7 +63,7 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-rdf-simple</artifactId>
-      <version>${ver.commonsrdf}</version>
+      <version>${ver.commons-rdf}</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/jena-fuseki2/jena-fuseki-ui/pom.xml b/jena-fuseki2/jena-fuseki-ui/pom.xml
index 6b7f378..aed2dbc 100644
--- a/jena-fuseki2/jena-fuseki-ui/pom.xml
+++ b/jena-fuseki2/jena-fuseki-ui/pom.xml
@@ -62,7 +62,7 @@
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
-                <version>1.13.4</version>
+                <version>1.14.0</version>
                 <executions>
                     <execution>
                         <id>install node and yarn</id>
diff --git a/jena-fuseki2/jena-fuseki-ui/yarn.lock b/jena-fuseki2/jena-fuseki-ui/yarn.lock
index e184487..04fea96 100644
--- a/jena-fuseki2/jena-fuseki-ui/yarn.lock
+++ b/jena-fuseki2/jena-fuseki-ui/yarn.lock
@@ -15,6 +15,14 @@
     "@jridgewell/gen-mapping" "^0.3.0"
     "@jridgewell/trace-mapping" "^0.3.9"
 
+"@babel/code-frame@^7.22.13":
+  version "7.22.13"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+  integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
+  dependencies:
+    "@babel/highlight" "^7.22.13"
+    chalk "^2.4.2"
+
 "@babel/code-frame@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658"
@@ -58,6 +66,16 @@
     "@jridgewell/trace-mapping" "^0.3.17"
     jsesc "^2.5.1"
 
+"@babel/generator@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+  integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+  dependencies:
+    "@babel/types" "^7.23.0"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
 "@babel/helper-compilation-targets@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02"
@@ -69,18 +87,23 @@
     lru-cache "^5.1.1"
     semver "^6.3.0"
 
+"@babel/helper-environment-visitor@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+  integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
 "@babel/helper-environment-visitor@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
   integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
 
-"@babel/helper-function-name@^7.22.5":
-  version "7.22.5"
-  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
-  integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
+"@babel/helper-function-name@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+  integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
   dependencies:
-    "@babel/template" "^7.22.5"
-    "@babel/types" "^7.22.5"
+    "@babel/template" "^7.22.15"
+    "@babel/types" "^7.23.0"
 
 "@babel/helper-hoist-variables@^7.22.5":
   version "7.22.5"
@@ -124,11 +147,23 @@
   dependencies:
     "@babel/types" "^7.22.5"
 
+"@babel/helper-split-export-declaration@^7.22.6":
+  version "7.22.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
+  integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-string-parser@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
   integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
 
+"@babel/helper-validator-identifier@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+  integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
 "@babel/helper-validator-identifier@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
@@ -148,6 +183,15 @@
     "@babel/traverse" "^7.22.5"
     "@babel/types" "^7.22.5"
 
+"@babel/highlight@^7.22.13":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
+  integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.22.20"
+    chalk "^2.4.2"
+    js-tokens "^4.0.0"
+
 "@babel/highlight@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031"
@@ -162,6 +206,11 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea"
   integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==
 
+"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+  integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
 "@babel/runtime@^7.21.0":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
@@ -169,6 +218,15 @@
   dependencies:
     regenerator-runtime "^0.13.11"
 
+"@babel/template@^7.22.15":
+  version "7.22.15"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+  integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
+  dependencies:
+    "@babel/code-frame" "^7.22.13"
+    "@babel/parser" "^7.22.15"
+    "@babel/types" "^7.22.15"
+
 "@babel/template@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
@@ -179,21 +237,30 @@
     "@babel/types" "^7.22.5"
 
 "@babel/traverse@^7.22.5":
-  version "7.22.5"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1"
-  integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==
+  version "7.23.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+  integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
   dependencies:
-    "@babel/code-frame" "^7.22.5"
-    "@babel/generator" "^7.22.5"
-    "@babel/helper-environment-visitor" "^7.22.5"
-    "@babel/helper-function-name" "^7.22.5"
+    "@babel/code-frame" "^7.22.13"
+    "@babel/generator" "^7.23.0"
+    "@babel/helper-environment-visitor" "^7.22.20"
+    "@babel/helper-function-name" "^7.23.0"
     "@babel/helper-hoist-variables" "^7.22.5"
-    "@babel/helper-split-export-declaration" "^7.22.5"
-    "@babel/parser" "^7.22.5"
-    "@babel/types" "^7.22.5"
+    "@babel/helper-split-export-declaration" "^7.22.6"
+    "@babel/parser" "^7.23.0"
+    "@babel/types" "^7.23.0"
     debug "^4.1.0"
     globals "^11.1.0"
 
+"@babel/types@^7.22.15", "@babel/types@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+  integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+  dependencies:
+    "@babel/helper-string-parser" "^7.22.5"
+    "@babel/helper-validator-identifier" "^7.22.20"
+    to-fast-properties "^2.0.0"
+
 "@babel/types@^7.22.5":
   version "7.22.5"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
@@ -1390,7 +1457,7 @@
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
-chalk@^2.0.0:
+chalk@^2.0.0, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2760,9 +2827,9 @@
   integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
 
 get-func-name@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
-  integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
+  integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
 
 get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
   version "1.2.1"
@@ -4385,9 +4452,9 @@
     util-deprecate "^1.0.2"
 
 postcss@^8.1.10, postcss@^8.4.23:
-  version "8.4.24"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df"
-  integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==
+  version "8.4.31"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+  integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
   dependencies:
     nanoid "^3.3.6"
     picocolors "^1.0.0"
diff --git a/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/SRSInfoTest.java b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/SRSInfoTest.java
index 0132b6d..81a9e19 100644
--- a/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/SRSInfoTest.java
+++ b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/SRSInfoTest.java
@@ -38,6 +38,7 @@
     public SRSInfoTest() {
     }
 
+
     @BeforeClass
     public static void setUpClass() {
     }
@@ -54,6 +55,18 @@
     public void tearDown() {
     }
 
+    // SIS 1.1
+    //public static final double OS_X1 = -104009.35713717458;
+    //public static final double OS_X2 = 688806.0073395987;
+    //public static final double OS_Y1 = -16627.734528041445;
+    //public static final double OS_Y2 = 1256558.4455361878;
+
+    // SIS 1.4
+    public static final double OS_X1 = -104009.35713717458;
+    public static final double OS_X2 = 688806.0073395987;
+    public static final double OS_Y1 = -16627.734528042376;
+    public static final double OS_Y2 = 1256558.445536187;
+
     /**
      * Test of buildDomainEnvelope method, of class SRSInfo.
      *
@@ -99,10 +112,12 @@
         CoordinateReferenceSystem crs = CRS.forCode(srsURI);
         Boolean isAxisXY = SRSInfo.checkAxisXY(crs);
 
-        // SIS 1.0
-        //Envelope expResult = new Envelope(-118397.00138845091, 751441.7790901454, -16627.734375018626, 1272149.3463499574);
-        // SIS 1.1
-        Envelope expResult = new Envelope(-104009.35713717458, 688806.0073395987, -16627.734528041445, 1256558.4455361878);
+
+        Envelope expResult = new Envelope(OS_X1, OS_X2, OS_Y1, OS_Y2);
+
+
+        //expected:<Env[-104009.35713717458 : 688806.0073395987, -16627.734528041445 : 1256558.4455361878]>
+        // but was:<Env[-104009.35713717458 : 688806.0073395987, -16627.734528042376 : 1256558.445536187]>
 
         Envelope result = SRSInfo.buildDomainEnvelope(crs, isAxisXY);
         assertEquals(expResult, result);
diff --git a/jena-geosparql/src/test/java/org/apache/jena/geosparql/spatial/SearchEnvelopeTest.java b/jena-geosparql/src/test/java/org/apache/jena/geosparql/spatial/SearchEnvelopeTest.java
index 5fa3746..371f18f 100644
--- a/jena-geosparql/src/test/java/org/apache/jena/geosparql/spatial/SearchEnvelopeTest.java
+++ b/jena-geosparql/src/test/java/org/apache/jena/geosparql/spatial/SearchEnvelopeTest.java
@@ -67,10 +67,15 @@
     //public static final double OS_Y1 = -16627.734375018626;
     //public static final double OS_Y2 = 1272149.3463499574;
     // SIS 1.1
+    //public static final double OS_X1 = -104009.35713717458;
+    //public static final double OS_X2 = 688806.0073395987;
+    //public static final double OS_Y1 = -16627.734528041445;
+    //public static final double OS_Y2 = 1256558.4455361878;
+    // SIS 1.4
     public static final double OS_X1 = -104009.35713717458;
     public static final double OS_X2 = 688806.0073395987;
-    public static final double OS_Y1 = -16627.734528041445;
-    public static final double OS_Y2 = 1256558.4455361878;
+    public static final double OS_Y1 = -16627.734528042376;
+    public static final double OS_Y2 = 1256558.445536187;
 
     /**
      * Test of build method, of class SearchEnvelope.
@@ -184,9 +189,12 @@
 
         GeometryWrapper geometryWrapper = GeometryWrapper.extract("<http://www.opengis.net/def/crs/EPSG/0/27700> POINT(10.0 20.0)", WKTDatatype.URI);
         CardinalDirection direction = CardinalDirection.EAST;
-        SearchEnvelope expResult = new SearchEnvelope(new Envelope(10, OS_X2, OS_Y1, OS_Y2), SpatialIndexTestData.OSGB_SRS_INFO);
+        SearchEnvelope expResult = new SearchEnvelope(new Envelope(10.0, OS_X2, OS_Y1, OS_Y2), SpatialIndexTestData.OSGB_SRS_INFO);
         SearchEnvelope result = SearchEnvelope.build(geometryWrapper, SpatialIndexTestData.OSGB_SRS_INFO, direction);
         assertEquals(expResult, result);
+
+        //java.lang.AssertionError: expected:<SearchEnvelope{envelope=Env[10.0 : 688806.0073395987, -16627.734528041445 : 1256558.4455361878], wrappedEnvelope=null}>
+        // but was:<SearchEnvelope{envelope=Env                          [10.0 : 688806.0073395987, -16627.734528042376 : 1256558.445536187], wrappedEnvelope=null}>
     }
 
     /**
diff --git a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
index 36cbeea..3b5f5d1 100644
--- a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
+++ b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
@@ -134,8 +134,6 @@
         if ( reorderTransform == null && warnAboutOptimizer )
             ARQ.getExecLogger().warn("No BGP optimizer");
 
-
-
         DatasetGraphTDB dsg = StoreConnection.connectCreate(storageLocation, params, reorderTransform).getDatasetGraphTDB();
         DatasetGraphSwitchable appDSG = new DatasetGraphSwitchable(path, containerLocation, dsg);
         return appDSG;
diff --git a/pom.xml b/pom.xml
index 4174da8..2534524 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,21 +58,21 @@
 
     <!-- Testing -->
     <ver.junit>4.13.2</ver.junit>  
-    <ver.mockito>5.4.0</ver.mockito>
+    <ver.mockito>5.6.0</ver.mockito>
     <ver.awaitility>4.2.0</ver.awaitility>
     <ver.contract.tests>0.2.0</ver.contract.tests>
 
     <!-- Dependencies -->
     <ver.slf4j>1.7.36</ver.slf4j>
-    <ver.log4j2>2.20.0</ver.log4j2>
+    <ver.log4j2>2.21.0</ver.log4j2>
 
-    <ver.lucene>9.5.0</ver.lucene>
+    <ver.lucene>9.7.0</ver.lucene>
 
-    <ver.jetty>10.0.15</ver.jetty>
+    <ver.jetty>10.0.17</ver.jetty>
     <ver.shiro>1.12.0</ver.shiro>
 
-    <ver.protobuf>3.23.4</ver.protobuf>
-    <ver.libthrift>0.18.1</ver.libthrift>
+    <ver.protobuf>3.24.3</ver.protobuf>
+    <ver.libthrift>0.19.0</ver.libthrift>
 
     <!-- JSON-LD 1.1 -->
     <ver.titanium-json-ld>1.3.2</ver.titanium-json-ld>
@@ -88,35 +88,35 @@
          and use that or later.
     -->
     <ver.jsonldjava>0.13.4</ver.jsonldjava>
-    <ver.jackson>2.15.2</ver.jackson>
+    <ver.jackson>2.15.3</ver.jackson>
     <ver.httpclient>4.5.14</ver.httpclient>
     <ver.httpcore>4.4.16</ver.httpcore>
 
-    <ver.caffeine>3.1.7</ver.caffeine>
+    <ver.caffeine>3.1.8</ver.caffeine>
     <!-- Most of Jena uses other libraries for equivalent functionality. -->
-    <ver.guava>32.1.2-jre</ver.guava>
+    <ver.guava>32.1.3-jre</ver.guava>
 
     <ver.gson>2.10.1</ver.gson>
-    <ver.commonsio>2.11.0</ver.commonsio>
-    <ver.commonscli>1.5.0</ver.commonscli>
-    <ver.commonslang3>3.12.0</ver.commonslang3>
-    <ver.commonsrdf>0.5.0</ver.commonsrdf>
-    <ver.commonscsv>1.10.0</ver.commonscsv>
-    <ver.commons-codec>1.15</ver.commons-codec>
-    <ver.commons-compress>1.23.0</ver.commons-compress>
+    <ver.commons-io>2.14.0</ver.commons-io>
+    <ver.commons-cli>1.5.0</ver.commons-cli>
+    <ver.commons-lang3>3.13.0</ver.commons-lang3>
+    <ver.commons-rdf>0.5.0</ver.commons-rdf>
+    <ver.commons-csv>1.10.0</ver.commons-csv>
+    <ver.commons-codec>1.16.0</ver.commons-codec>
+    <ver.commons-compress>1.24.0</ver.commons-compress>
     <ver.commons-collections>4.4</ver.commons-collections>
     <ver.dexxcollection>0.7</ver.dexxcollection>
-    <ver.micrometer>1.11.2</ver.micrometer>
-    <ver.roaringbitmap>0.9.47</ver.roaringbitmap>
+    <ver.micrometer>1.11.4</ver.micrometer>
+    <ver.roaringbitmap>1.0.0</ver.roaringbitmap>
 
     <!-- For testing, not shipped -->
-    <ver.graalvm>23.0.1</ver.graalvm>
+    <ver.graalvm>22.3.4</ver.graalvm>
     <ver.jython>2.7.3</ver.jython>
-    <ver.org.openjdk.jmh>1.36</ver.org.openjdk.jmh>
+    <ver.org.openjdk.jmh>1.37</ver.org.openjdk.jmh>
 
     <!--- GeoSPARQL related -->
     <ver.jcommander>1.82</ver.jcommander>
-    <ver.sis>1.1</ver.sis>
+    <ver.sis>1.4</ver.sis>
     <ver.jts>1.19.0</ver.jts>
 
     <!-- 
@@ -306,7 +306,7 @@
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
-         <version>${ver.commonsio}</version>
+         <version>${ver.commons-io}</version>
        </dependency>
        
        <dependency>
@@ -342,41 +342,48 @@
          <artifactId>libthrift</artifactId>
          <version>${ver.libthrift}</version>
          <exclusions>
-           <!-- Use whatever version Jena is using -->
-           <exclusion>
-             <groupId>org.apache.httpcomponents</groupId>
-             <artifactId>httpcore</artifactId>
-           </exclusion>
            <exclusion>
              <groupId>org.apache.commons</groupId>
              <artifactId>commons-lang3</artifactId>
            </exclusion>
-           <!-- libthrift : 0.14.0 onwards : THRIFT-5375 -->
-           <exclusion>
-             <groupId>org.apache.tomcat.embed</groupId>
-             <artifactId>tomcat-embed-core</artifactId>
-           </exclusion>
-           <exclusion>
-             <groupId>javax.servlet</groupId>
-             <artifactId>javax.servlet-api</artifactId>
-           </exclusion>
            <exclusion>
              <groupId>org.slf4j</groupId>
              <artifactId>*</artifactId>
            </exclusion>
+
+           <!-- 
+                Jena does not use the RPC capabilities of Thrift,
+                only the binary data format.
+           -->
+           <exclusion>
+             <groupId>org.apache.httpcomponents.client5</groupId>
+             <artifactId>*</artifactId>
+           </exclusion>
+           <exclusion>
+             <groupId>org.apache.httpcomponents.core5</groupId>
+             <artifactId>*</artifactId>
+           </exclusion>
+           <exclusion>
+             <groupId>jakarta.servlet</groupId>
+             <artifactId>*</artifactId>
+           </exclusion>
+           <exclusion>
+             <groupId>jakarta.annotation</groupId>
+             <artifactId>*</artifactId>
+           </exclusion>
          </exclusions>
        </dependency>
 
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-csv</artifactId>
-         <version>${ver.commonscsv}</version>
+         <version>${ver.commons-csv}</version>
        </dependency>
 
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
-         <version>${ver.commonslang3}</version>
+         <version>${ver.commons-lang3}</version>
        </dependency>
 
        <dependency>
@@ -702,13 +709,13 @@
        <dependency>
          <groupId>commons-cli</groupId>
          <artifactId>commons-cli</artifactId>
-         <version>${ver.commonscli}</version>
+         <version>${ver.commons-cli}</version>
        </dependency>
 
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-rdf-api</artifactId>
-         <version>${ver.commonsrdf}</version>
+         <version>${ver.commons-rdf}</version>
        </dependency>
 
        <dependency>