You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2013/04/08 23:11:15 UTC

svn commit: r1465789 - in /jena/Experimental/jena-jdbc: jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/ jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/ jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/ jena-j...

Author: rvesse
Date: Mon Apr  8 21:11:15 2013
New Revision: 1465789

URL: http://svn.apache.org/r1465789
Log:
Stubs towards a command pre-processor extension mechanism for Jena JDBC

Modified:
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/CommandPreProcessor.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaStatement.java
    jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java?rev=1465789&r1=1465788&r2=1465789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java Mon Apr  8 21:11:15 2013
@@ -22,10 +22,9 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-
 import org.apache.jena.jdbc.JdbcCompatibility;
 import org.apache.jena.jdbc.statements.DatasetStatement;
+import org.apache.jena.jdbc.statements.JenaStatement;
 
 import com.hp.hpl.jena.query.Dataset;
 
@@ -83,12 +82,12 @@ public abstract class DatasetConnection 
     }
 
     @Override
-    protected Statement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+    protected JenaStatement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
             throws SQLException {
         if (resultSetType != ResultSet.TYPE_FORWARD_ONLY)
             throw new SQLException("Dataset backed connections currently only supports forward-only result sets");
         if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
-            throw new SQLException("Database backed connections currently only supports read-only result sets");
+            throw new SQLException("Database backed connections only supports read-only result sets");
         return new DatasetStatement(this, ResultSet.FETCH_FORWARD, 0, resultSetHoldability, this.getAutoCommit(),
                 this.getTransactionIsolation());
     }

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java?rev=1465789&r1=1465788&r2=1465789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java Mon Apr  8 21:11:15 2013
@@ -37,16 +37,41 @@ import java.sql.Savepoint;
 import java.sql.Statement;
 import java.sql.Struct;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
 import org.apache.jena.jdbc.JdbcCompatibility;
 import org.apache.jena.jdbc.metadata.JenaMetadata;
+import org.apache.jena.jdbc.preprocessing.CommandPreProcessor;
+import org.apache.jena.jdbc.statements.JenaStatement;
+
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.update.UpdateRequest;
 
 /**
  * Abstract base implementation of a Jena JDBC connection
- * 
+ * <p>
+ * Generally speaking this is a faithful implementation of a JDBC connection but
+ * it also provides a couple of Jena JDBC specific features:
+ * </p>
+ * <ol>
+ * <li>JDBC compatibility level</li>
+ * <li>Command pre-processors</li>
+ * </ol>
+ * <p>
+ * The JDBC compatibility level allows the API to behave slightly differently
+ * depending on how JDBC like you need it to be, see {@link JdbcCompatibility}
+ * for more discussion on this.
+ * </p>
+ * <p>
+ * Command pre-processors are an extension mechanism designed to allow Jena JDBC
+ * connections to cope with the fact that the tools consuming the API may be
+ * completely unaware that we speak SPARQL rather than SQL. They allow for
+ * manipulation of incoming command text as well as manipulation of the parsed
+ * SPARQL queries and updates as desired.
+ * </p>
  */
 public abstract class JenaConnection implements Connection {
 
@@ -71,6 +96,7 @@ public abstract class JenaConnection imp
     private int isolationLevel = DEFAULT_ISOLATION_LEVEL;
     private int compatibilityLevel = JdbcCompatibility.DEFAULT;
     private List<Statement> statements = new ArrayList<Statement>();
+    private List<CommandPreProcessor> preProcessors = new ArrayList<CommandPreProcessor>();
 
     /**
      * Creates a new connection
@@ -120,6 +146,112 @@ public abstract class JenaConnection imp
         this.compatibilityLevel = JdbcCompatibility.normalizeLevel(level);
     }
 
+    /**
+     * Adds a command pre-processor to the connection
+     * 
+     * @param preProcessor
+     *            Pre-processor to add
+     */
+    public void addPreProcessor(CommandPreProcessor preProcessor) {
+        if (preProcessor == null)
+            return;
+        this.preProcessors.add(preProcessor);
+    }
+
+    /**
+     * Inserts a command pre-processor for the connection
+     * 
+     * @param index
+     *            Index to insert at
+     * @param preProcessor
+     *            Pre-processor
+     */
+    public void insertPreProcessor(int index, CommandPreProcessor preProcessor) {
+        if (preProcessor == null)
+            return;
+        this.preProcessors.add(index, preProcessor);
+    }
+
+    /**
+     * Removes a command pre-processor from the connection
+     * 
+     * @param preProcessor
+     *            Pre-processor to remove
+     */
+    public void removePreProcessor(CommandPreProcessor preProcessor) {
+        if (preProcessor == null)
+            return;
+        this.preProcessors.remove(preProcessor);
+    }
+
+    /**
+     * Removes a command pre-processor from the connection
+     * 
+     * @param index
+     *            Index to remove at
+     */
+    public void removePreProcessor(int index) {
+        this.preProcessors.remove(index);
+    }
+
+    /**
+     * Clears all command pre-processor from the connection
+     */
+    public void clearPreProcessors() {
+        this.preProcessors.clear();
+    }
+
+    /**
+     * Gets the currently registered pre-processors for the connection
+     * 
+     * @return Iterator of pre-processors
+     */
+    public Iterator<CommandPreProcessor> getPreProcessors() {
+        return this.preProcessors.iterator();
+    }
+    
+    /**
+     * Apply registered pre-processors to the given command text
+     * @param text Command Text
+     * @return Command Text after processing by registered pre-processors
+     * @throws SQLException
+     */
+    public String applyPreProcessors(String text) throws SQLException {
+        for (CommandPreProcessor preProcessor : this.preProcessors) {
+            if (preProcessor == null) continue;
+            text = preProcessor.preProcessCommandText(text);
+        }
+        return text;
+    }
+    
+    /**
+     * Applies registered pre-processors to the given query
+     * @param q Query
+     * @return Query after processing by registered pre-processors
+     * @throws SQLException
+     */
+    public Query applyPreProcessors(Query q) throws SQLException {
+        for (CommandPreProcessor preProcessor : this.preProcessors) {
+            if (preProcessor == null) continue;
+            q = preProcessor.preProcessQuery(q);
+        }
+        return q;
+    }
+    
+    /**
+     * Applies registered pre-processors to the given update
+     * @param u Update
+     * @return Update after processing by registered pre-processors
+     * @throws SQLException
+     */
+    public UpdateRequest applyPreProcessors(UpdateRequest u) throws SQLException {
+        for (CommandPreProcessor preProcessor : this.preProcessors) {
+            if (preProcessor == null) continue;
+            u = preProcessor.preProcessUpdate(u);
+        }
+        return u;
+    }
+
     @Override
     public boolean isWrapperFor(Class<?> arg0) throws SQLException {
         throw new SQLFeatureNotSupportedException();
@@ -222,12 +354,12 @@ public abstract class JenaConnection imp
             throws SQLException {
         if (this.isClosed())
             throw new SQLException("Cannot create a statement after the connection was closed");
-        Statement stmt = this.createStatementInternal(resultSetType, resultSetConcurrency, resultSetHoldability);
+        JenaStatement stmt = this.createStatementInternal(resultSetType, resultSetConcurrency, resultSetHoldability);
         this.statements.add(stmt);
         return stmt;
     }
 
-    protected abstract Statement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+    protected abstract JenaStatement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
             throws SQLException;
 
     @Override

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/CommandPreProcessor.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/CommandPreProcessor.java?rev=1465789&r1=1465788&r2=1465789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/CommandPreProcessor.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/preprocessing/CommandPreProcessor.java Mon Apr  8 21:11:15 2013
@@ -17,6 +17,7 @@
  */
 package org.apache.jena.jdbc.preprocessing;
 
+import java.sql.SQLException;
 import java.sql.Statement;
 
 import com.hp.hpl.jena.query.Query;
@@ -39,30 +40,47 @@ public interface CommandPreProcessor {
     /**
      * Pre-process incoming command text
      * <p>
-     * This is invoked before Jena JDBC has attempted to determine whether the text is a query/update.  This allows an application to do textual clean up/alteration of the incoming command if it so desires.
+     * This is invoked before Jena JDBC has attempted to determine whether the
+     * text is a query/update. This allows an application to do textual clean
+     * up/alteration of the incoming command if it so desires.
      * </p>
-     * @param text Command Text
+     * 
+     * @param text
+     *            Command Text
      * @return Command Text which may have been altered
+     * @throws SQLException
+     *             Thrown if pre-processing encounters an issue
      */
-    public String preProcessCommandText(String text);
+    public String preProcessCommandText(String text) throws SQLException;
 
     /**
      * Pre-process a query
      * <p>
-     * This is invoked during query execution prior to Jena JDBC making any of its own manipulations on the query e.g. using {@link Statement#setMaxRows(int)} to add a {@code LIMIT} clause.
+     * This is invoked during query execution prior to Jena JDBC making any of
+     * its own manipulations on the query e.g. using
+     * {@link Statement#setMaxRows(int)} to add a {@code LIMIT} clause.
      * </p>
-     * @param q Query
+     * 
+     * @param q
+     *            Query
      * @return Query which may have been altered
+     * @throws SQLException
+     *             Thrown if pre-processing encounters an issue
      */
-    public Query preProcessQuery(Query q);
-    
+    public Query preProcessQuery(Query q) throws SQLException;
+
     /**
      * Pre-process an update
      * <p>
-     * This is invoked during update execution prior to Jena JDBC making any of its own manipulations on the update.
+     * This is invoked during update execution prior to Jena JDBC making any of
+     * its own manipulations on the update.
      * </p>
-     * @param u Update
+     * 
+     * @param u
+     *            Update
      * @return Update which may have been altered
+     * @throws SQLException
+     *             Thrown if pre-processing encounters an issue
      */
-    public UpdateRequest preProcessUpdate(UpdateRequest u);
+    public UpdateRequest preProcessUpdate(UpdateRequest u) throws SQLException;
 }

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaStatement.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaStatement.java?rev=1465789&r1=1465788&r2=1465789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaStatement.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaStatement.java Mon Apr  8 21:11:15 2013
@@ -186,6 +186,9 @@ public abstract class JenaStatement impl
     public final boolean execute(String sql) throws SQLException {
         if (this.isClosed())
             throw new SQLException("The Statement is closed");
+        
+        // Pre-process the command text
+        sql = this.connection.applyPreProcessors(sql);
 
         Query q = null;
         UpdateRequest u = null;
@@ -216,7 +219,7 @@ public abstract class JenaStatement impl
     private boolean executeQuery(Query q) throws SQLException {
         if (this.isClosed())
             throw new SQLException("The Statement is closed");
-
+        
         // Do we need transactions?
         boolean needsBegin = (!this.autoCommit && this.transactionLevel != Connection.TRANSACTION_NONE && !this
                 .hasActiveTransaction());
@@ -229,6 +232,9 @@ public abstract class JenaStatement impl
             } else if (needsBegin) {
                 this.beginTransaction(ReadWrite.WRITE);
             }
+            
+            // Pre-process the query
+            q = this.connection.applyPreProcessors(q);
 
             // Manipulate the query if appropriate
             if (this.maxRows > NO_LIMIT) {
@@ -302,7 +308,11 @@ public abstract class JenaStatement impl
             if (needsCommit || needsBegin) {
                 this.beginTransaction(ReadWrite.WRITE);
             }
+            
+            // Pre-process the update
+            u = this.connection.applyPreProcessors(u);
 
+            // Execute updates
             UpdateProcessor processor = this.createUpdateProcessor(u);
             processor.execute();
             commit = true;

Modified: jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java?rev=1465789&r1=1465788&r2=1465789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java Mon Apr  8 21:11:15 2013
@@ -24,12 +24,11 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-
 import org.apache.jena.jdbc.JdbcCompatibility;
 import org.apache.jena.jdbc.connections.JenaConnection;
 import org.apache.jena.jdbc.remote.metadata.RemoteEndpointMetadata;
 import org.apache.jena.jdbc.remote.statements.RemoteEndpointStatement;
+import org.apache.jena.jdbc.statements.JenaStatement;
 
 /**
  * Represents a connection to a remote endpoint
@@ -89,7 +88,7 @@ public class RemoteEndpointConnection ex
     }
 
     @Override
-    protected Statement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+    protected JenaStatement createStatementInternal(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
             throws SQLException {
         if (this.isClosed())
             throw new SQLException("Cannot create a statement after the connection was closed");