Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphConnection.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphConnection.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphConnection.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphConnection.java
 Thu Apr  9 02:22:47 2015
@@ -18,121 +18,107 @@
  
 package org.apache.jena.client.graph;
 
-import org.apache.jena.client.ConnectionBase;
-import org.apache.jena.client.QueryStatement;
-import org.apache.jena.client.UpdateStatement;
-import org.apache.jena.client.Updater;
-
-import com.hp.hpl.jena.query.Query;
-import com.hp.hpl.jena.query.ReadWrite;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import com.hp.hpl.jena.sparql.core.Transactional;
-import com.hp.hpl.jena.update.Update;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.client.AbstractConnection ;
+import org.apache.jena.client.QueryStatement ;
+import org.apache.jena.client.UpdateStatement ;
+import org.apache.jena.client.Updater ;
+
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.update.GraphStoreFactory ;
+import com.hp.hpl.jena.update.Update ;
 
-public class DatasetGraphConnection extends ConnectionBase
+public class DatasetGraphConnection extends AbstractConnection
 {
     private final DatasetGraph dsg;
+    private final Transactional tx;
     
     private boolean autoCommitMode = true;
     
-    DatasetGraphConnection(DatasetGraphRepository repo, DatasetGraph dsg)
+    DatasetGraphConnection(DatasetGraphDatabaseClient repo, DatasetGraph dsg, 
Transactional tx)
     {
         super(repo);
         this.dsg = dsg;
-    }
-    
-    @Override
-    protected Updater doCreateStreamingUpdater()
-    {
-        DatasetGraphUpdater updater = new DatasetGraphUpdater(dsg, 
autoCommitMode);
-        updater.open();
-        return updater;
+        this.tx = tx;
     }
     
     @Override
     public QueryStatement doCreateQueryStatement(String queryString)
     {
-        return new DatasetGraphQueryStatement(queryString, dsg, this);
+        return new DatasetGraphQueryStatement(queryString, dsg, tx, 
autoCommitMode, this);
     }
 
     @Override
     public QueryStatement doCreateQueryStatement(Query query)
     {
-        return new DatasetGraphQueryStatement(query, dsg, this);
+        return new DatasetGraphQueryStatement(query, dsg, tx, autoCommitMode, 
this);
     }
     
     @Override
     public UpdateStatement doCreateUpdateStatement(String updateString)
     {
-        return new DatasetGraphUpdateStatement(updateString, this);
+        return new DatasetGraphUpdateStatement(updateString, 
GraphStoreFactory.create(dsg), autoCommitMode, this);
     }
 
     @Override
     public UpdateStatement doCreateUpdateStatement(Update update)
     {
-        return new DatasetGraphUpdateStatement(update, this);
+        return new DatasetGraphUpdateStatement(update, 
GraphStoreFactory.create(dsg), autoCommitMode, this);
     }
     
     @Override
     public UpdateStatement doCreateUpdateStatement(Iterable<? extends Update> 
updates)
     {
-        return new DatasetGraphUpdateStatement(updates, this);
+        return new DatasetGraphUpdateStatement(updates, 
GraphStoreFactory.create(dsg), autoCommitMode, this);
+    }
+    
+    @Override
+    protected UpdateStatement doCreateUpdateStatement(Action<Updater> action)
+    {
+        return new DatasetGraphUpdateStatement(action, 
GraphStoreFactory.create(dsg), autoCommitMode, this);
     }
     
     @Override
     public boolean supportsTransactions()
     {
-        return dsg instanceof Transactional;
+        return (null != tx);
     }
 
     @Override
     public void begin(ReadWrite readWrite)
     {
         autoCommitMode = false;
-        if (supportsTransactions())
-        {
-            ((Transactional)dsg).begin(readWrite);
-        }
+        if (supportsTransactions()) tx.begin(readWrite);
     }
 
     @Override
     public void commit()
     {
         autoCommitMode = true;
-        if (supportsTransactions())
-        {
-            ((Transactional)dsg).commit();
-        }
+        if (supportsTransactions()) tx.commit();
     }
 
     @Override
     public void abort()
     {
         autoCommitMode = true;
-        if (supportsTransactions())
-        {
-            ((Transactional)dsg).abort();
-        }
+        if (supportsTransactions()) tx.abort();
     }
     
     @Override
     public void end()
     {
         autoCommitMode = true;
-        if (supportsTransactions())
-        {
-            ((Transactional)dsg).end();
-        }
+        if (supportsTransactions()) tx.end();
     }
 
     @Override
     public boolean isInTransaction()
     {
-        if (supportsTransactions())
-        {
-            return ((Transactional)dsg).isInTransaction();
-        }
-        return false;
+        return supportsTransactions() && tx.isInTransaction();
     }
-    
+
 }

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphDatabaseClient.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphDatabaseClient.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphDatabaseClient.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphDatabaseClient.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jena.client.graph;
+
+import org.apache.jena.client.Connection ;
+import org.apache.jena.client.DatabaseClient ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+
+/**
+ * A DatabaseClient wrapped around a local DatasetGraph.
+ */
+public class DatasetGraphDatabaseClient implements DatabaseClient
+{
+    private final DatasetGraph dsg;
+    private final Transactional tx;
+    
+    /**
+     * Construct a DatasetGraphDatabaseClient over the specified DatasetGraph.
+     * 
+     * @param dsg the DatasetGraph on which to base this DatabaseClient
+     * @param tx the Transactional object to use for transactions; or null if 
no transactions desired
+     */
+    public DatasetGraphDatabaseClient(DatasetGraph dsg, Transactional tx)
+    {
+        this.dsg = dsg;
+        this.tx = tx;
+    }
+
+    @Override
+    public Connection getConnection()
+    {
+        return new DatasetGraphConnection(this, dsg, tx);
+    }
+    
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphQueryStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphQueryStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphQueryStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphQueryStatement.java
 Thu Apr  9 02:22:47 2015
@@ -17,38 +17,47 @@
  */
 package org.apache.jena.client.graph;
 
-import org.apache.jena.client.QueryStatement;
-import org.apache.jena.client.QueryStatementBase;
+import org.apache.jena.client.QueryStatement ;
+import org.apache.jena.client.AbstractQueryStatement ;
 
-import com.hp.hpl.jena.query.Query;
-import com.hp.hpl.jena.query.QueryExecution;
-import com.hp.hpl.jena.query.QueryExecutionFactory;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import com.hp.hpl.jena.sparql.core.DatasetImpl;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryExecution ;
+import com.hp.hpl.jena.query.QueryExecutionFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetImpl ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
 
-class DatasetGraphQueryStatement extends QueryStatementBase<QueryExecution> 
implements QueryStatement
+class DatasetGraphQueryStatement extends 
AbstractQueryStatement<QueryExecution> implements QueryStatement
 {
     private final DatasetGraph dsg;
+    private final Transactional tx;
+    private final boolean autoCommitMode;
     
-    DatasetGraphQueryStatement(String queryString, DatasetGraph dsg, 
DatasetGraphConnection connection)
+    DatasetGraphQueryStatement(String queryString, DatasetGraph dsg, 
Transactional tx, boolean autoCommitMode, DatasetGraphConnection connection)
     {
         super(queryString, connection);
         this.dsg = dsg;
+        this.tx = tx;
+        this.autoCommitMode = autoCommitMode;
     }
     
-    DatasetGraphQueryStatement(Query query, DatasetGraph dsg, 
DatasetGraphConnection connection)
+    DatasetGraphQueryStatement(Query query, DatasetGraph dsg, Transactional 
tx, boolean autoCommitMode, DatasetGraphConnection connection)
     {
         super(query, connection);
         this.dsg = dsg;
+        this.tx = tx;
+        this.autoCommitMode = autoCommitMode;
     }
     
     @Override
+    @SuppressWarnings("resource")  // Suppress the warning that 
AutoCommitQueryExection is not used within a try-with-resources block
     protected QueryExecution createQueryExecution()
     {
-        QueryExecution qe = (null != queryString) ?
+        final QueryExecution qe = (null != queryString) ?
             QueryExecutionFactory.create(queryString, DatasetImpl.wrap(dsg)) :
             QueryExecutionFactory.create(queryObject, DatasetImpl.wrap(dsg));
-        return qe;
+
+        return (autoCommitMode && (null != tx)) ? new 
AutoCommitQueryExecution(qe, tx) : qe;
     }
     
 }

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdateStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdateStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdateStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdateStatement.java
 Thu Apr  9 02:22:47 2015
@@ -17,24 +17,92 @@
  */
 package org.apache.jena.client.graph;
 
-import org.apache.jena.client.UpdateStatementBase;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.client.AbstractUpdateStatement ;
+import org.apache.jena.client.UpdateExecution ;
+import org.apache.jena.client.Updater ;
 
-import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.sparql.modify.UpdateEngine ;
+import com.hp.hpl.jena.sparql.modify.UpdateEngineFactory ;
+import com.hp.hpl.jena.sparql.modify.UpdateEngineRegistry ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.update.GraphStore ;
+import com.hp.hpl.jena.update.Update ;
 
-class DatasetGraphUpdateStatement extends UpdateStatementBase
+class DatasetGraphUpdateStatement extends AbstractUpdateStatement
 {
-    DatasetGraphUpdateStatement(String updateString, DatasetGraphConnection 
connection)
+    private final GraphStore graphStore;
+    private final boolean autoCommitMode;
+    
+    DatasetGraphUpdateStatement(String updateString, GraphStore graphStore, 
boolean autoCommitMode, DatasetGraphConnection connection)
     {
         super(updateString, connection);
+        this.graphStore = graphStore;
+        this.autoCommitMode = autoCommitMode;
     }
     
-    DatasetGraphUpdateStatement(Update update, DatasetGraphConnection 
connection)
+    DatasetGraphUpdateStatement(Update update, GraphStore graphStore, boolean 
autoCommitMode, DatasetGraphConnection connection)
     {
         super(update, connection);
+        this.graphStore = graphStore;
+        this.autoCommitMode = autoCommitMode;
     }
     
-    DatasetGraphUpdateStatement(Iterable<? extends Update> updates, 
DatasetGraphConnection connection)
+    DatasetGraphUpdateStatement(Iterable<? extends Update> updates, GraphStore 
graphStore, boolean autoCommitMode, DatasetGraphConnection connection)
     {
         super(updates, connection);
+        this.graphStore = graphStore;
+        this.autoCommitMode = autoCommitMode;
+    }
+    
+    DatasetGraphUpdateStatement(Action<Updater> action, GraphStore graphStore, 
boolean autoCommitMode, DatasetGraphConnection connection)
+    {
+        super(action, connection);
+        this.graphStore = graphStore;
+        this.autoCommitMode = autoCommitMode;
+    }
+    
+    @Override
+    protected UpdateExecution createUpdateExecution()
+    {
+        // Copy the global context to freeze it.
+        final Context context = new Context(ARQ.getContext());
+        
+        return new UpdateExecution()
+        {
+            @Override
+            public void execUpdate(Action<Updater> action)
+            {
+                final UpdateEngineFactory factory = 
UpdateEngineRegistry.findFactory(graphStore, context);
+                final UpdateEngine updateEngine = factory.create(graphStore, 
null, context);
+                
+                final boolean performTransaction = autoCommitMode && 
graphStore instanceof Transactional;
+                final Transactional tx = performTransaction ? 
(Transactional)graphStore : null;
+                if (performTransaction) tx.begin(ReadWrite.WRITE);
+                try
+                {
+                    try (UpdateEngineUpdater updater = new 
UpdateEngineUpdater(updateEngine))
+                    {
+                        updater.open();
+                        action.apply(updater);
+                    }
+                    if (performTransaction) tx.commit();
+                }
+                finally
+                {
+                    if (performTransaction) tx.end();
+                }
+                
+            }
+        };
+    }
+    
+    @Override
+    public void cancel()
+    {
+        // do nothing
     }
 }

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/UpdateEngineUpdater.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/UpdateEngineUpdater.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/UpdateEngineUpdater.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/UpdateEngineUpdater.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.client.graph;
+
+import java.util.Iterator ;
+
+import org.apache.jena.client.AbstractUpdater ;
+
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.modify.UpdateEngine ;
+import com.hp.hpl.jena.sparql.modify.UpdateSink ;
+import com.hp.hpl.jena.sparql.modify.request.QuadDataAccSink ;
+import com.hp.hpl.jena.update.Update ;
+
+class UpdateEngineUpdater extends AbstractUpdater implements AutoCloseable
+{
+    private final UpdateEngine updateEngine;
+    
+    public UpdateEngineUpdater(UpdateEngine updateEngine)
+    {
+        this.updateEngine = updateEngine;
+    }
+    
+    public void open()
+    {
+        updateEngine.startRequest();
+    }
+    
+    @Override
+    public void close()
+    {
+        updateEngine.finishRequest();
+    }
+
+    @Override
+    protected void doInsert(Iterator<? extends Quad> quadIter)
+    {
+        UpdateSink sink = updateEngine.getUpdateSink();
+        try
+        {
+            QuadDataAccSink quadSink = sink.createInsertDataSink();
+            try
+            {
+                while (quadIter.hasNext())
+                {
+                    Quad quad = quadIter.next();
+                    quadSink.addQuad(quad);
+                }
+            }
+            finally
+            {
+                quadSink.close();
+            }
+        }
+        finally
+        {
+            sink.close();
+        }
+    }
+
+    @Override
+    protected void doDelete(Iterator<? extends Quad> quadIter)
+    {
+        UpdateSink sink = updateEngine.getUpdateSink();
+        try
+        {
+            QuadDataAccSink quadSink = sink.createDeleteDataSink();
+            try
+            {
+                while (quadIter.hasNext())
+                {
+                    Quad quad = quadIter.next();
+                    quadSink.addQuad(quad);
+                }
+            }
+            finally
+            {
+                quadSink.close();
+            }
+        }
+        finally
+        {
+            sink.close();
+        }
+    }
+
+    @Override
+    protected void doUpdate(Iterator<? extends Update> updateIter)
+    {
+        UpdateSink sink = updateEngine.getUpdateSink();
+        try
+        {
+            while (updateIter.hasNext())
+            {
+                Update update = updateIter.next();
+                sink.send(update);
+            }
+        }
+        finally
+        {
+            sink.close();
+        }
+    }
+
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpConnection.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpConnection.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpConnection.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpConnection.java
 Thu Apr  9 02:22:47 2015
@@ -17,46 +17,34 @@
  */
 package org.apache.jena.client.http;
 
-import org.apache.jena.client.ConnectionBase;
-import org.apache.jena.client.QueryStatement;
-import org.apache.jena.client.UpdateStatement;
-import org.apache.jena.client.Updater;
-import org.apache.jena.riot.WebContent ;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.client.AbstractConnection ;
+import org.apache.jena.client.QueryStatement ;
+import org.apache.jena.client.UpdateStatement ;
+import org.apache.jena.client.Updater ;
 
-import com.hp.hpl.jena.query.Query;
-import com.hp.hpl.jena.query.ReadWrite;
-import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.update.Update ;
 
-public class HttpConnection extends ConnectionBase
+public class HttpConnection extends AbstractConnection
 {
     private final String queryEndpoint;
     private final String updateEndpoint;
-    
-    private boolean useContentTypeSPARQLUpdate = true;
+    private final HttpAuthenticator authenticator;
     
     private String selectContentType = null;
     private String modelContentType = null;
     private String askContentType = null;
-    
     private String updateContentType = null;
     
-    HttpConnection(HttpRepository repo, String queryEndpoint, String 
updateEndpoint)
+    HttpConnection(HttpDatabaseClient dc, final String queryEndpoint, final 
String updateEndpoint, final HttpAuthenticator authenticator)
     {
-        super(repo);
+        super(dc);
         this.queryEndpoint = queryEndpoint;
         this.updateEndpoint = updateEndpoint;
-    }
-    
-    /**
-     * Whether or not to use <code>"application/sparql-update"</code> as the 
content type for SPARQL Update.  Defaults to true.
-     * If set to false then <code>"application/x-www-form-urlencoded"</code> 
is used instead (however, be warned that urlencoded
-     * is not streaming and will buffer the entire update into memory.
-     * 
-     * @param useContentTypeSPARQLUpdate true if 
<code>"application/sparql-update"</code> is desired; true is the default
-     */
-    public void useContentTypeSPARQLUpdate(boolean useContentTypeSPARQLUpdate)
-    {
-        this.updateContentType = useContentTypeSPARQLUpdate ? 
WebContent.contentTypeSPARQLUpdate : WebContent.contentTypeHTMLForm;
+        this.authenticator = authenticator;
     }
     
     /**
@@ -89,54 +77,60 @@ public class HttpConnection extends Conn
         this.askContentType = contentType;
     }
     
-    @Override
-    protected Updater doCreateStreamingUpdater()
-    {
-        if (null == updateEndpoint)
-            throw new IllegalStateException("Cannot create an Updater because 
the update endpoint URL has not been set");
-        HttpUpdater updater = new HttpUpdater(updateEndpoint, 
updateContentType);
-        updater.open();
-        return updater;
+    /**
+     * Sets the Content Type for SPARQL Update queries.  The two supported 
types are: <code>"application/sparql-update"</code>
+     * and <code>"application/x-www-form-urlencoded"</code>.  Setting this to 
<code>null</code> will use the default,
+     * which is <code>"application/sparql-update"</code>
+     * <p>
+     * <strong>Warning:</strong> If 
<code>"application/x-www-form-urlencoded"</code> is used then the update is not 
streaming
+     * and must be buffered entirely into memory before being submitted to the 
server.
+     * 
+     * @param contentType the Content Type to use for SPARQL Update queries
+     */
+    public void setUpdateContentType(String contentType) {
+        this.updateContentType = contentType;
     }
     
     @Override
-    public QueryStatement doCreateQueryStatement(String queryString)
+    protected QueryStatement doCreateQueryStatement(String queryString)
     {
-        if (null == queryEndpoint)
-            throw new IllegalStateException("Cannot create a QueryStatement 
because the query endpoint URL has not been set");
-        return new HttpQueryStatement(queryString, queryEndpoint, this, 
selectContentType, modelContentType, askContentType);
+        if (null == queryEndpoint) throw new IllegalStateException("Cannot 
create a QueryStatement because the query endpoint URL has not been set");
+        return new HttpQueryStatement(queryString, queryEndpoint, 
authenticator, this, selectContentType, modelContentType, askContentType);
     }
 
     @Override
-    public QueryStatement doCreateQueryStatement(Query query)
+    protected QueryStatement doCreateQueryStatement(Query query)
     {
-        if (null == queryEndpoint)
-            throw new IllegalStateException("Cannot create a QueryStatement 
because the query endpoint URL has not been set");
-        return new HttpQueryStatement(query, queryEndpoint, this, 
selectContentType, modelContentType, askContentType);
+        if (null == queryEndpoint) throw new IllegalStateException("Cannot 
create a QueryStatement because the query endpoint URL has not been set");
+        return new HttpQueryStatement(query, queryEndpoint, authenticator, 
this, selectContentType, modelContentType, askContentType);
     }
     
     @Override
-    public UpdateStatement doCreateUpdateStatement(String updateString)
+    protected UpdateStatement doCreateUpdateStatement(String updateString)
     {
-        if (null == updateEndpoint)
-            throw new IllegalStateException("Cannot create an UpdateStatement 
because the update endpoint URL has not been set");
-        return new HttpUpdateStatement(updateString, this);
+        if (null == updateEndpoint) throw new IllegalStateException("Cannot 
create an UpdateStatement because the update endpoint URL has not been set");
+        return new HttpUpdateStatement(updateString, updateEndpoint, 
authenticator, this, updateContentType);
     }
 
     @Override
-    public UpdateStatement doCreateUpdateStatement(Update update)
+    protected UpdateStatement doCreateUpdateStatement(Update update)
+    {
+        if (null == updateEndpoint) throw new IllegalStateException("Cannot 
create an UpdateStatement because the update endpoint URL has not been set");
+        return new HttpUpdateStatement(update, updateEndpoint, authenticator, 
this, updateContentType);
+    }
+    
+    @Override
+    protected UpdateStatement doCreateUpdateStatement(Iterable<? extends 
Update> updates)
     {
-        if (null == updateEndpoint)
-            throw new IllegalStateException("Cannot create an UpdateStatement 
because the update endpoint URL has not been set");
-        return new HttpUpdateStatement(update, this);
+        if (null == updateEndpoint) throw new IllegalStateException("Cannot 
create an UpdateStatement because the update endpoint URL has not been set");
+        return new HttpUpdateStatement(updates, updateEndpoint, authenticator, 
this, updateContentType);
     }
     
     @Override
-    public UpdateStatement doCreateUpdateStatement(Iterable<? extends Update> 
updates)
+    protected UpdateStatement doCreateUpdateStatement(Action<Updater> action)
     {
-        if (null == updateEndpoint)
-            throw new IllegalStateException("Cannot create an UpdateStatement 
because the update endpoint URL has not been set");
-        return new HttpUpdateStatement(updates, this);
+        if (null == updateEndpoint) throw new IllegalStateException("Cannot 
create an UpdateStatement because the update endpoint URL has not been set");
+        return new HttpUpdateStatement(action, updateEndpoint, authenticator, 
this, updateContentType);
     }
     
     @Override

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpDatabaseClient.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpDatabaseClient.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpDatabaseClient.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpDatabaseClient.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jena.client.http;
+
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.client.Connection;
+import org.apache.jena.client.DatabaseClient;
+
+/**
+ * A DatabaseClient wrapped around a remote HTTP SPARQL endpoint.
+ * <p>
+ * <strong>Note:</strong> Databases other than Jena Fuseki may be severely 
limited on the type and size
+ * of SPARQL 1.1 Update queries.  For example, Sesame (and Sesame-based 
endpoints) have two main limitations:
+ * <ol>
+ *   <li>
+ *     Sesame only supports the {@code "application/x-www-form-urlencoded"} 
content-type.  By default DatabaseClient
+ *     will use the {@code "application/sparql-update"} content-type, but it 
can be changed to use 
+ *     {@code "application/x-www-form-urlencoded"} by setting the appropriate 
type on the {@link HttpDatabaseClient} object.
+ *     <code>
+ *     <pre>
+ * HttpDatabaseClient client = 
DatabaseClientFactory.createRemote(queryEndpoint, updateEndpoint);
+ * client.setUpdateContentType(WebContent.contentTypeHTMLForm);</pre>
+ *     </code>
+ *     <strong>Warning:</strong> When 
<code>"application/x-www-form-urlencoded"</code> is used then the update 
request will not be
+ *     streaming and will be buffered entirely into memory before being 
submitted to the server.
+ *   </li>
+ *   <p><br>
+ *   <li>
+ *     Sesame parses SPARQL Update request into an in-memory Abstract Syntax 
Tree (AST) completely before executing the
+ *     query.  This can cause two issues: 1) an update request with a large 
number of operations may cause a an OutOfMemoryException;
+ *     and 2) INSERT DATA and DELETE DATA operations are not streamed into the 
underlying repository, and large such operations
+ *     may cause either an OutOfMemoryException or a StackOverflowException.
+ *     <p><br>
+ *     <strong>Note:</strong> Sesame may not actually report the true 
exception, rather it seems to report
+ *     {@code org.openrdf.http.server.ClientHTTPException: Unsupported MIME 
type: application/x-www-form-urlencoded} when
+ *     a large update requst is submitted.
+ *     <p><br>
+ *     The work-around for this issue is to break your update query into 
smaller chunks and submit them as separate update requests.
+ *   </li>
+ * </ol>
+ */
+public class HttpDatabaseClient implements DatabaseClient
+{
+    private final String queryEndpoint;
+    private final String updateEndpoint;
+    private final HttpAuthenticator authenticator;
+    
+    private String selectContentType = null;
+    private String modelContentType = null;
+    private String askContentType = null;
+    
+    private String updateContentType = null;
+    
+    /**
+     * Construct a HttpDatabaseClient over the specified HTTP SPARQL endpoint.
+     * 
+     * @param queryEndpoint the SPARQL query endpoint URL; if null, then you 
may not execute queries against the endpoint
+     * @param updateEndpoint the SPARQL update endpoint URL; if null, then you 
may not execute updates against the endpoint
+     * @param authenticator the HTTP authenticator to use; if null, then no 
authenticator is used
+     */
+    public HttpDatabaseClient(final String queryEndpoint, final String 
updateEndpoint, final HttpAuthenticator authenticator)
+    {
+        this.queryEndpoint = queryEndpoint;
+        this.updateEndpoint = updateEndpoint;
+        this.authenticator = authenticator;
+    }
+
+    @Override
+    public Connection getConnection()
+    {
+        HttpConnection conn = new HttpConnection(this, queryEndpoint, 
updateEndpoint, authenticator);
+        conn.setSelectContentType(selectContentType);
+        conn.setModelContentType(modelContentType);
+        conn.setAskContentType(askContentType);
+        conn.setUpdateContentType(updateContentType);
+        return conn;
+    }
+    
+    /**
+     * Sets the Content Type for SELECT queries provided that the format is 
supported.
+     * Setting this to <code>null</code> will use Jena's default.
+     *  
+     * @param contentType the Content Type to use for SELECT queries
+     */
+    public void setSelectContentType(String contentType) {
+        this.selectContentType = contentType;
+    }
+    
+    /**
+     * Sets the Content Type for CONSTRUCT/DESCRIBE queries provided that the 
format is supported.
+     * Setting this to <code>null</code> will use Jena's default.
+     *  
+     * @param contentType the Content Type to use for CONSTRUCT/DESCRIBE 
queries
+     */
+    public void setModelContentType(String contentType) {
+        this.modelContentType = contentType;
+    }
+    
+    /**
+     * Sets the Content Type for ASK queries provided that the format is 
supported.
+     * Setting this to <code>null</code> will use Jena's default.
+     *  
+     * @param contentType the Content Type to use for ASK queries
+     */
+    public void setAskContentType(String contentType) {
+        this.askContentType = contentType;
+    }
+    
+    /**
+     * Sets the Content Type for SPARQL Update requests.  The two supported 
types are: <code>"application/sparql-update"</code>
+     * and <code>"application/x-www-form-urlencoded"</code>.  Setting this to 
<code>null</code> will use the default,
+     * which is <code>"application/sparql-update"</code>
+     * <p>
+     * <strong>Warning:</strong> If 
<code>"application/x-www-form-urlencoded"</code> is used then the update 
request is not streaming
+     * and will be buffered entirely into memory before being submitted to the 
server.
+     * 
+     * @param contentType the Content Type to use for SPARQL Update queries
+     */
+    public void setUpdateContentType(String contentType) {
+        this.updateContentType = contentType;
+    }
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpQueryStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpQueryStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpQueryStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpQueryStatement.java
 Thu Apr  9 02:22:47 2015
@@ -17,42 +17,49 @@
  */
 package org.apache.jena.client.http;
 
-import org.apache.jena.client.QueryStatement;
-import org.apache.jena.client.QueryStatementBase;
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.client.QueryStatement ;
+import org.apache.jena.client.AbstractQueryStatement ;
 
-import com.hp.hpl.jena.query.Query;
-import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ;
 
-class HttpQueryStatement extends QueryStatementBase<QueryEngineHTTP> 
implements QueryStatement
+class HttpQueryStatement extends AbstractQueryStatement<QueryEngineHTTP> 
implements QueryStatement
 {
     private final String queryEndpoint;
+    private final HttpAuthenticator authenticator;
     private final String selectContentType;
     private final String modelContentType;
     private final String askContentType;
     
-    HttpQueryStatement(String queryString, String queryEndpoint, 
HttpConnection connection, String selectContentType, String modelContentType, 
String askContentType)
+    HttpQueryStatement(String queryString, String queryEndpoint, 
HttpAuthenticator authenticator, HttpConnection connection, String 
selectContentType, String modelContentType, String askContentType)
     {
         super(queryString, connection);
         this.queryEndpoint = queryEndpoint;
+        this.authenticator = authenticator;
         this.selectContentType = selectContentType;
         this.modelContentType = modelContentType;
         this.askContentType = askContentType;
     }
     
-    HttpQueryStatement(Query query, String queryEndpoint, HttpConnection 
connection, String selectContentType, String modelContentType, String 
askContentType)
+    HttpQueryStatement(Query query, String queryEndpoint, HttpAuthenticator 
authenticator, HttpConnection connection, String selectContentType, String 
modelContentType, String askContentType)
     {
         super(query, connection);
         this.queryEndpoint = queryEndpoint;
+        this.authenticator = authenticator;
         this.selectContentType = selectContentType;
         this.modelContentType = modelContentType;
         this.askContentType = askContentType;
     }
     
+    @Override
     protected QueryEngineHTTP createQueryExecution()
     {
         QueryEngineHTTP qe = (null != queryString) ?
-            new QueryEngineHTTP(queryEndpoint, queryString) :
-            new QueryEngineHTTP(queryEndpoint, queryObject);
+            new QueryEngineHTTP(queryEndpoint, queryString, authenticator) :
+            new QueryEngineHTTP(queryEndpoint, queryObject, authenticator);
+        
+        qe.setTimeout(timeout1, timeout2);
         
         if (null != selectContentType) 
qe.setSelectContentType(selectContentType);
         if (null != modelContentType) qe.setModelContentType(modelContentType);

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateExecution.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateExecution.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateExecution.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateExecution.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jena.client.http;
+
+import java.io.ByteArrayOutputStream ;
+import java.io.UnsupportedEncodingException ;
+import java.nio.charset.UnsupportedCharsetException ;
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.Map ;
+
+import org.apache.http.Consts ;
+import org.apache.http.HttpEntity ;
+import org.apache.http.NameValuePair ;
+import org.apache.http.client.entity.UrlEncodedFormEntity ;
+import org.apache.http.message.BasicNameValuePair ;
+import org.apache.http.protocol.HttpContext ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.atlas.web.auth.SimpleAuthenticator ;
+import org.apache.jena.client.UpdateExecution ;
+import org.apache.jena.client.Updater ;
+import org.apache.jena.riot.WebContent ;
+import org.apache.jena.riot.web.HttpOp ;
+import org.apache.jena.riot.web.HttpResponseLib ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ;
+import com.hp.hpl.jena.sparql.engine.http.Service ;
+import com.hp.hpl.jena.sparql.modify.request.UpdateWriter ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.sparql.util.Symbol ;
+
+class HttpUpdateExecution implements UpdateExecution
+{
+    private static Logger log = 
LoggerFactory.getLogger(HttpUpdateExecution.class);
+    
+    /**
+     * Symbol used to set a {@link HttpContext} which will be used for HTTP 
requests
+     */
+    public static final Symbol HTTP_CONTEXT = Symbol.create("httpContext");
+    
+    private final String updateEndpoint;
+    private final SerializationContext sCxt;
+    private final String contentType;
+    private final Context context;
+    private HttpAuthenticator authenticator;
+    
+    protected long connectTimeout = -1;
+    protected long readTimeout = -1;
+    
+    public HttpUpdateExecution(final String updateEndpoint, final 
HttpAuthenticator authenticator, String contentType, final SerializationContext 
sCxt)
+    {
+        if (null == updateEndpoint) throw new 
NullPointerException("updateEndpoint");
+        if (null == contentType) contentType = 
WebContent.contentTypeSPARQLUpdate;
+        
+        if (!WebContent.contentTypeSPARQLUpdate.equals(contentType) && 
!WebContent.contentTypeHTMLForm.equals(contentType))
+        {
+            throw new IllegalArgumentException("Content-Type must be " + 
WebContent.contentTypeSPARQLUpdate + " or " + WebContent.contentTypeHTMLForm + 
".  Was:" + contentType);
+        }
+        
+        this.updateEndpoint = updateEndpoint;
+        this.contentType = contentType;
+        this.sCxt = sCxt;
+        
+        // Copy the global context to freeze it.
+        this.context = new Context(ARQ.getContext());
+
+        // Apply service configuration if relevant
+        HttpUpdateExecution.applyServiceConfig(updateEndpoint, this);
+        
+        // Don't want to overwrite credentials we may have picked up from
+        // service context in the parent constructor if the specified
+        // authenticator is null
+        if (authenticator != null) {
+            this.authenticator = authenticator;
+        }
+    }
+    
+    /**
+     * <p>
+     * Helper method which applies configuration from the Context to the query
+     * engine if a service context exists for the given URI
+     * </p>
+     * <p>
+     * Based off proposed patch for JENA-405 but modified to apply all relevant
+     * configuration, this is in part also based off of the private
+     * {@code configureQuery()} method of the {@link Service} class though it
+     * omits parameter merging since that will be done automatically whenever
+     * the {@link QueryEngineHTTP} instance makes a query for remote 
submission.
+     * </p>
+     * 
+     * @param serviceURI
+     *            Service URI
+     */
+    private static void applyServiceConfig(String serviceURI, 
HttpUpdateExecution engine) {
+        @SuppressWarnings("unchecked")
+        Map<String, Context> serviceContextMap = (Map<String, Context>) 
engine.context.get(Service.serviceContext);
+        if (serviceContextMap != null && 
serviceContextMap.containsKey(serviceURI)) {
+            Context serviceContext = serviceContextMap.get(serviceURI);
+            if (log.isDebugEnabled())
+                log.debug("Endpoint URI {} has SERVICE Context: {} ", 
serviceURI, serviceContext);
+
+            // Apply authentication settings
+            String user = serviceContext.getAsString(Service.queryAuthUser);
+            String pwd = serviceContext.getAsString(Service.queryAuthPwd);
+
+            if (user != null || pwd != null) {
+                user = user == null ? "" : user;
+                pwd = pwd == null ? "" : pwd;
+                if (log.isDebugEnabled())
+                    log.debug("Setting basic HTTP authentication for endpoint 
URI {} with username: {} ", serviceURI, user);
+
+//                engine.setAuthentication(user, pwd.toCharArray());
+                engine.authenticator = new SimpleAuthenticator(user, 
pwd.toCharArray());
+            }
+        }
+    }
+    
+    /** 
+     * Set time, in milliseconds
+     */
+    public void setTimeout(long connectTimeout, long readTimeout)
+    {
+        this.connectTimeout = connectTimeout;
+        this.readTimeout = readTimeout;
+    }
+    
+    @Override
+    public void execUpdate(Action<Updater> action)
+    {
+        HttpEntity entity;
+        if (WebContent.contentTypeSPARQLUpdate.equals(contentType))
+        {
+            entity = new SparqlUpdateEntity(action, sCxt);
+        }
+        else if (WebContent.contentTypeHTMLForm.equals(contentType))
+        {
+            // There is no streaming if "application/x-www-form-urlencoded" is 
used.  Instead everything will be buffered into memory.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            IndentedWriter iw = new IndentedWriter(baos);
+            try
+            {
+                UpdateWriter writer = new UpdateWriter(iw, sCxt);
+                writer.open();
+                try
+                {
+                    action.apply(new UpdateWriterUpdater(writer));
+                }
+                finally
+                {
+                    writer.close();
+                }
+            }
+            finally
+            {
+                iw.close();
+            }
+            
+            String updateString ;
+            try
+            {
+                updateString = baos.toString(Consts.UTF_8.name()) ;
+            }
+            catch (UnsupportedEncodingException e)
+            {
+                // should never happen
+                throw new UnsupportedCharsetException(Consts.UTF_8.name());
+            }
+            baos = null;
+            
+            List<NameValuePair> formparams = new ArrayList<>();
+            formparams.add(new BasicNameValuePair("update", updateString));
+            updateString = null;
+            
+            entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
+        }
+        else {
+            throw new IllegalArgumentException("Content-Type must be " + 
WebContent.contentTypeSPARQLUpdate + " or " + WebContent.contentTypeHTMLForm + 
".  Was:" + contentType);
+        }
+        
+        // TODO Apply timeouts
+        if (connectTimeout > 0) {
+            
+        }
+        if (readTimeout > 0) {
+            
+        }
+        
+        HttpOp.execHttpPost(updateEndpoint, entity, null, 
HttpResponseLib.nullResponse, null, (HttpContext)context.get(HTTP_CONTEXT), 
authenticator) ;
+    }
+
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateStatement.java
 Thu Apr  9 02:22:47 2015
@@ -17,24 +17,63 @@
  */
 package org.apache.jena.client.http;
 
-import org.apache.jena.client.UpdateStatementBase;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.client.UpdateExecution ;
+import org.apache.jena.client.AbstractUpdateStatement ;
+import org.apache.jena.client.Updater ;
 
-import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.update.Update ;
 
-class HttpUpdateStatement extends UpdateStatementBase
+class HttpUpdateStatement extends AbstractUpdateStatement
 {
-    HttpUpdateStatement(String updateString, HttpConnection connection)
+    private final String updateEndpoint;
+    private final HttpAuthenticator authenticator;
+    private final String updateContentType;
+    
+    HttpUpdateStatement(String updateString, String updateEndpoint,  
HttpAuthenticator authenticator, HttpConnection connection, String 
updateContentType)
     {
         super(updateString, connection);
+        this.updateEndpoint = updateEndpoint;
+        this.authenticator = authenticator;
+        this.updateContentType = updateContentType;
     }
     
-    HttpUpdateStatement(Update update, HttpConnection connection)
+    HttpUpdateStatement(Update update, String updateEndpoint, 
HttpAuthenticator authenticator, HttpConnection connection, String 
updateContentType)
     {
         super(update, connection);
+        this.updateEndpoint = updateEndpoint;
+        this.authenticator = authenticator;
+        this.updateContentType = updateContentType;
     }
     
-    HttpUpdateStatement(Iterable<? extends Update> updates, HttpConnection 
connection)
+    HttpUpdateStatement(Iterable<? extends Update> updates, String 
updateEndpoint, HttpAuthenticator authenticator, HttpConnection connection, 
String updateContentType)
     {
         super(updates, connection);
+        this.updateEndpoint = updateEndpoint;
+        this.authenticator = authenticator;
+        this.updateContentType = updateContentType;
+    }
+    
+    HttpUpdateStatement(Action<Updater> action, String updateEndpoint, 
HttpAuthenticator authenticator, HttpConnection connection, String 
updateContentType)
+    {
+        super(action, connection);
+        this.updateEndpoint = updateEndpoint;
+        this.authenticator = authenticator;
+        this.updateContentType = updateContentType;
+    }
+
+    @Override
+    protected UpdateExecution createUpdateExecution()
+    {
+        HttpUpdateExecution ue = new HttpUpdateExecution(updateEndpoint, 
authenticator, updateContentType, null);
+        ue.setTimeout(timeout1, timeout2);
+        return ue;
+    }
+    
+    @Override
+    public void cancel()
+    {
+        // do nothing
     }
 }

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/SparqlUpdateEntity.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/SparqlUpdateEntity.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/SparqlUpdateEntity.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/SparqlUpdateEntity.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.client.http;
+
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.OutputStream ;
+
+import org.apache.http.entity.AbstractHttpEntity ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.client.Updater ;
+import org.apache.jena.riot.WebContent ;
+
+import com.hp.hpl.jena.sparql.modify.request.UpdateWriter ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+
+class SparqlUpdateEntity extends AbstractHttpEntity
+{
+    private final Action<Updater> action;
+    private final SerializationContext sCxt;
+    
+    SparqlUpdateEntity(Action<Updater> action, SerializationContext sCxt) {
+        this.action = action;
+        this.sCxt = sCxt;
+        this.setContentType(WebContent.contentTypeSPARQLUpdate);
+    }
+    
+
+    @Override
+    public boolean isRepeatable()
+    {
+        return false ;
+    }
+
+    @Override
+    public long getContentLength()
+    {
+        return -1 ;
+    }
+
+    @Override
+    public boolean isStreaming()
+    {
+        return true ;
+    }
+    
+    @Override
+    public InputStream getContent() throws IOException, IllegalStateException
+    {
+        throw new IllegalStateException("SparqlUpdateEntity is only meant to 
be used as a Request entity.");
+    }
+
+    @Override
+    public void writeTo(OutputStream out) throws IOException
+    {
+        IndentedWriter iw = new IndentedWriter(out);
+        UpdateWriter writer = new UpdateWriter(iw, sCxt);
+        writer.open();
+        try
+        {
+            action.apply(new UpdateWriterUpdater(writer));
+        }
+        finally
+        {
+            writer.close();
+        }
+        iw.flush();
+    }
+}

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateWriterUpdater.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateWriterUpdater.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateWriterUpdater.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateWriterUpdater.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.client.http;
+
+import java.util.Iterator ;
+
+import org.apache.jena.client.AbstractUpdater ;
+
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.modify.request.UpdateWriter ;
+import com.hp.hpl.jena.update.Update ;
+
+class UpdateWriterUpdater extends AbstractUpdater implements AutoCloseable
+{
+    private final UpdateWriter writer;
+    
+    public UpdateWriterUpdater(UpdateWriter writer)
+    {
+        this.writer = writer;
+    }
+
+    @Override
+    protected void doInsert(Iterator<? extends Quad> quadIter)
+    {
+        writer.insert(quadIter);
+    }
+
+    @Override
+    protected void doDelete(Iterator<? extends Quad> quadIter)
+    {
+        writer.delete(quadIter);
+    }
+
+    @Override
+    protected void doUpdate(Iterator<? extends Update> updateIter)
+    {
+        writer.update(updateIter);
+    }
+
+    @Override
+    public void close()
+    {
+        writer.close();
+    }
+}

Added: 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/AutoCommitQueryExecutionTest.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/AutoCommitQueryExecutionTest.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/AutoCommitQueryExecutionTest.java
 (added)
+++ 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/AutoCommitQueryExecutionTest.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.client.graph;
+
+import org.junit.Before ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.QueryExecution ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.sparql.core.TransactionalNull ;
+
+import static org.fest.assertions.Assertions.* ;
+import static org.mockito.Mockito.* ;
+
+public class AutoCommitQueryExecutionTest
+{
+    private Transactional tx;
+    private QueryExecution qe;
+    
+    @Before
+    public void setup()
+    {
+        tx = spy(new TransactionalNull());
+        qe = mock(QueryExecution.class);
+    }
+    
+    
+    @Test
+    public void itShouldPerformTransactionOnSelect()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execSelect();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+    
+    @Test
+    public void itShouldPerformTransactionOnAsk()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execAsk();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+    
+    @Test
+    public void itShouldPerformTransactionOnConstruct()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execConstruct();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+    
+    @Test
+    public void itShouldPerformTransactionOnConstructTriples()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execConstructTriples();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+    
+    @Test
+    public void itShouldPerformTransactionOnDescribe()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execDescribe();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+    
+    @Test
+    public void itShouldPerformTransactionOnDescribeTriples()
+    {
+        try(QueryExecution acqe = new AutoCommitQueryExecution(qe, tx))
+        {
+            assertThat(tx.isInTransaction()).isFalse();
+            acqe.execDescribeTriples();
+            verify(tx).begin(ReadWrite.READ);
+        }
+        verify(tx).end();
+        assertThat(tx.isInTransaction()).isFalse();
+    }
+}

Added: 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/DatasetGraphTest.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/DatasetGraphTest.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/DatasetGraphTest.java
 (added)
+++ 
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/DatasetGraphTest.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,507 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.client.graph;
+
+import java.io.ByteArrayInputStream ;
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.client.Connection ;
+import org.apache.jena.client.DatabaseClient ;
+import org.apache.jena.client.DatabaseClientFactory ;
+import org.apache.jena.client.QueryStatement ;
+import org.apache.jena.client.Updater ;
+import org.apache.jena.riot.Lang ;
+import org.apache.log4j.ConsoleAppender ;
+import org.apache.log4j.Level ;
+import org.apache.log4j.Logger ;
+import org.apache.log4j.PatternLayout ;
+import org.junit.Before ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.query.DatasetFactory ;
+import com.hp.hpl.jena.query.QueryExecException ;
+import com.hp.hpl.jena.query.QueryParseException ;
+import com.hp.hpl.jena.query.QuerySolution ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.query.ResultSet ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.sparql.ARQException ;
+import com.hp.hpl.jena.sparql.JenaTransactionException ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphTrackActive ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.update.GraphStore ;
+
+import static org.fest.assertions.Assertions.* ;
+import static org.mockito.Mockito.* ;
+
+public class DatasetGraphTest
+{
+    // Set up logging so it doesn't complain
+    static
+    {
+        final Logger rootLogger = Logger.getRootLogger();
+        rootLogger.setLevel(Level.WARN);
+        rootLogger.addAppender(new ConsoleAppender(new PatternLayout("%-6r 
[%p] %c - %m%n")));
+    }
+    
+    private CopyOnTxGraphStore dsg;
+    private DatabaseClient client;
+    
+    @Before
+    public void setup()
+    {
+        dsg = spy(new CopyOnTxGraphStore(DatasetGraphFactory.createMem()));
+        client = DatabaseClientFactory.createLocal(dsg);
+    }
+    
+    private void loadData(final String data)
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.createUpdateStatement(new Action<Updater>() {
+                @Override
+                public void apply(Updater up)
+                {
+                    up.insert(null, new ByteArrayInputStream(data.getBytes()), 
Lang.TURTLE);
+                }
+            }).execUpdate();
+        }
+    }
+    
+    
+    
+    @Test(expected = JenaTransactionException.class)
+    public void itShouldQueryWithNoTransaction()
+    {
+        try(Connection conn = DatabaseClientFactory.createLocal(dsg, 
null).getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("select * where 
{ ?s ?p ?o }"))
+            {
+                qs.execSelect();
+            }
+        }
+    }
+    
+    @Test
+    public void itShouldDoAutoCommitTransaction()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("select * where 
{ ?s ?p ?o }"))
+            {
+                qs.execSelect();
+            }
+        }
+        verify(dsg).begin(ReadWrite.READ);
+        verify(dsg).end();
+    }
+    
+    @Test(expected = ARQException.class)
+    public void itShouldThrowIfAccessedAfterQueryStatementIsClosed()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            ResultSet rs;
+            try(QueryStatement qs = conn.createQueryStatement("select * where 
{ ?s ?p ?o }"))
+            {
+                rs = qs.execSelect();
+            }
+            rs.hasNext();  // bad!
+        }
+    }
+    
+    @Test
+    public void itShouldHandleManualReadTransaction()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.READ);
+            try
+            {
+                try(QueryStatement qs = conn.createQueryStatement("select * 
where { ?s ?p ?o }"))
+                {
+                    qs.execSelect();
+                }
+                conn.commit();
+            }
+            finally
+            {
+                conn.end();
+            }
+        }
+        verify(dsg).begin(ReadWrite.READ);
+        verify(dsg).commit();
+        verify(dsg).end();
+    }
+    
+    @Test
+    public void itShouldHandleManualWriteTransaction()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                try(QueryStatement qs = conn.createQueryStatement("select * 
where { ?s ?p ?o }"))
+                {
+                    qs.execSelect();
+                }
+                conn.commit();
+            }
+            finally
+            {
+                conn.end();
+            }
+        }
+        verify(dsg).begin(ReadWrite.WRITE);
+        verify(dsg).commit();
+        verify(dsg).end();
+    }
+    
+    @Test
+    public void itShouldHandleTransactionAbort()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                try(QueryStatement qs = conn.createQueryStatement("select * 
where { ?s ?p ?o }"))
+                {
+                    qs.execSelect();
+                }
+                conn.abort();
+            }
+            finally
+            {
+                conn.end();
+            }
+        }
+        verify(dsg).begin(ReadWrite.WRITE);
+        verify(dsg).abort();
+        verify(dsg).end();
+    }
+    
+    @Test(expected = QueryExecException.class)
+    public void itShouldRequireTheCorrectQueryType()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("ask { ?s ?p ?o 
}"))
+            {
+                qs.execSelect();
+            }
+        }
+    }
+    
+    @Test
+    public void itShouldGetSelectResults()
+    {
+        loadData(
+            "@prefix : <http://example.org/>\n" +
+            ":a :b :c ."
+        );
+        
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("select * where 
{ ?s ?p ?o }"))
+            {
+                ResultSet rs = qs.execSelect();
+                assertThat(rs.hasNext());
+                QuerySolution row = rs.next();
+                
assertThat(row.getResource("s").getURI()).isEqualTo("http://example.org/a";);
+                
assertThat(row.getResource("p").getURI()).isEqualTo("http://example.org/b";);
+                
assertThat(row.getResource("o").getURI()).isEqualTo("http://example.org/c";);
+            }
+        }
+    }
+    
+    @Test
+    public void itShouldGetAskResults()
+    {
+        loadData(
+            "@prefix : <http://example.org/>\n" +
+            ":a :b :c ."
+        );
+        
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("ask { ?s ?p ?o 
}"))
+            {
+                assertThat(qs.execAsk()).isTrue();
+            }
+        }
+    }
+    
+    @Test
+    public void itShouldGetConstructResults()
+    {
+        loadData(
+            "@prefix : <http://example.org/>\n" +
+            ":a :b :c ."
+        );
+        
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("construct where 
{ ?s ?p ?o }"))
+            {
+                Model m = qs.execConstruct();
+                assertThat(m.size()).isEqualTo(1);
+            }
+        }
+    }
+    
+    @Test
+    public void itShouldGetDescribeResults()
+    {
+        loadData(
+            "@prefix : <http://example.org/>\n" +
+            ":a :b :c ."
+        );
+        
+        try(Connection conn = client.getConnection())
+        {
+            try(QueryStatement qs = conn.createQueryStatement("describe 
<http://example.org/a>"))
+            {
+                Model m = qs.execDescribe();
+                assertThat(m.size()).isEqualTo(1);
+            }
+        }
+    }
+    
+    @Test(expected = IllegalStateException.class)
+    public void itShouldOnlyAllowOneOperationAtATime()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                conn.createQueryStatement("select * where { ?s ?p ?o }");
+                conn.createUpdateStatement("prefix : <http://example.org/>\n 
insert data { :a :b :c }");
+                conn.commit();
+            }
+            finally
+            {
+                conn.end();
+            }
+        }
+    }
+    
+    
+    // Update tests
+    
+    @Test
+    public void itShouldCommit()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isFalse();
+                conn.createUpdateStatement("prefix : <http://example.org/>\n 
insert data { :a :b :c }").execUpdate();;
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isTrue();
+                conn.commit();
+            }
+            finally
+            {
+                conn.end();
+            }
+            assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isTrue();
+        }
+    }
+    
+    @Test
+    public void itShouldRollbackOnAbort()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isFalse();
+                conn.createUpdateStatement("prefix : <http://example.org/>\n 
insert data { :a :b :c }").execUpdate();;
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isTrue();
+                conn.abort();
+            }
+            finally
+            {
+                conn.end();
+            }
+            assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isFalse();
+        }
+        verify(dsg).abort();
+    }
+    
+    @Test
+    public void itShouldRollbackOnException()
+    {
+        try(Connection conn = client.getConnection())
+        {
+            conn.begin(ReadWrite.WRITE);
+            try
+            {
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isFalse();
+                conn.createUpdateStatement("prefix : <http://example.org/>\n 
insert data { :a :b :c }").execUpdate();;
+                assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isTrue();
+                
+                conn.createQueryStatement("monkey pod").execAsk();
+                conn.commit();
+            }
+            catch (QueryParseException e)
+            {
+                // Ignore 
+            }
+            finally
+            {
+                conn.end();
+            }
+            assertThat(conn.createQueryStatement("ask { ?s ?p ?o 
}").execAsk()).isFalse();
+        }
+    }
+    
+    
+    
+    /**
+     * Doesn't provide thread-safe transactions, but otherwise does honor 
transaction semantics and ensures that all operations occur inside of a 
transaction boundary
+     */
+    private static class CopyOnTxGraphStore extends DatasetGraphTrackActive 
implements GraphStore
+    {
+        private final DatasetGraph dsg;
+        private DatasetGraph dsgWork;
+        private ReadWrite txState;
+        
+        public CopyOnTxGraphStore(DatasetGraph dsg)
+        {
+            this.dsg = dsg;
+            this.txState = null;
+        }
+        
+        @Override
+        public DatasetGraph get()
+        {
+            if (!isInTransaction()) throw new JenaTransactionException("Not in 
a transaction");
+            return dsgWork;
+        }
+
+        @Override
+        public Context getContext()
+        {
+            return dsg.getContext();
+        }
+
+        @Override
+        protected void checkActive()
+        {
+            if (!isInTransaction()) throw new JenaTransactionException("Not in 
a transaction");
+        }
+
+        @Override
+        protected void checkNotActive()
+        {
+            if (isInTransaction()) throw new 
JenaTransactionException("Currently in a transaction");
+        }
+
+        @Override
+        public boolean isInTransaction()
+        {
+            return (null != txState);
+        }
+        
+        private static void copy(DatasetGraph source, DatasetGraph dest)
+        {
+            if (source != dest)
+            {
+                dest.clear();
+                for(Iterator<Quad> it = source.find(null); it.hasNext(); )
+                {
+                    dest.add(it.next());
+                }
+            }
+        }
+
+        @Override
+        protected void _begin(ReadWrite readWrite)
+        {
+            txState = readWrite;
+            if (ReadWrite.WRITE.equals(readWrite))
+            {
+                dsgWork = DatasetGraphFactory.createMem();
+                copy(dsg, dsgWork);
+            }
+            else
+            {
+                dsgWork = dsg;
+            }
+        }
+
+        @Override
+        protected void _commit()
+        {
+            txState = null;
+            copy(dsgWork, dsg);
+            dsgWork = null;
+        }
+
+        @Override
+        protected void _abort()
+        {
+            txState = null;
+            dsgWork = null;
+        }
+
+        @Override
+        protected void _end()
+        {
+            if (null != txState)
+            {
+                _abort();
+            }
+        }
+
+        @Override
+        protected void _close()
+        {
+            _end();
+        }
+
+        @Override
+        public Dataset toDataset()
+        {
+            checkActive();
+            return DatasetFactory.create(dsgWork);
+        }
+
+        @Override
+        public void startRequest()
+        {
+        }
+
+        @Override
+        public void finishRequest()
+        {
+        }
+    }
+}


Reply via email to