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/25 02:00:12 UTC
svn commit: r1471789 - in /jena/Experimental/jena-jdbc:
jena-jdbc-core/src/main/java/org/apache/jena/jdbc/
jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/
jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/
jena-jdbc-driver-...
Author: rvesse
Date: Thu Apr 25 00:00:12 2013
New Revision: 1471789
URL: http://svn.apache.org/r1471789
Log:
Putting in place support for DriverParameterInfo on Driver implementations, not yet complete
Modified:
jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/JenaDriver.java
jena/Experimental/jena-jdbc/jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/MemDriver.java
jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/RemoteEndpointDriver.java
jena/Experimental/jena-jdbc/jena-jdbc-driver-tdb/src/main/java/org/apache/jena/jdbc/tdb/TDBDriver.java
Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/JenaDriver.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/JenaDriver.java?rev=1471789&r1=1471788&r2=1471789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/JenaDriver.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/JenaDriver.java Thu Apr 25 00:00:12 2013
@@ -28,6 +28,7 @@ import java.util.Locale;
import java.util.Map.Entry;
import java.util.Properties;
+import org.apache.jena.atlas.lib.StrUtils;
import org.apache.jena.jdbc.connections.JenaConnection;
import org.apache.jena.jdbc.preprocessing.CommandPreProcessor;
@@ -188,65 +189,8 @@ public abstract class JenaDriver impleme
if (!this.acceptsURL(url))
return null;
- // Create new empty properties if necessary
- Properties ps = new Properties();
-
- // Parse out the key value pairs from the connection URL
- url = url.substring(DRIVER_PREFIX.length() + this.implPrefix.length());
- String[] kvps = url.split("&|;");
- for (int i = 0; i < kvps.length; i++) {
- String kvp = kvps[i];
- if (kvp.length() == 0)
- continue;
-
- // Try to split into key and value
- String key, value;
- if (kvp.contains("=")) {
- String[] temp = kvp.split("=", 2);
- key = temp[0];
- value = temp[1];
- } else {
- key = kvp;
- value = null;
- }
-
- // All keys are normalized to lower case using the English Locale
- key = key.toLowerCase(Locale.ENGLISH);
-
- // Put into properties appropriately
- if (!ps.containsKey(key)) {
- // Doesn't yet exist, add a string/list as appropriate
- if (this.allowsMultipleValues(key)) {
- List<String> values = new ArrayList<String>();
- values.add(value);
- ps.put(key, values);
- } else {
- ps.put(key, value);
- }
- } else if (this.allowsMultipleValues(key)) {
- // If it allows multiple values append to those existing
- Object currValue = ps.get(key);
- if (currValue instanceof List<?>) {
- // Can just append to existing list
- ((List<Object>) currValue).add(value);
- } else {
- // Convert to list
- List<String> values = new ArrayList<String>();
- values.add(currValue.toString());
- values.add(value);
- ps.put(key, values);
- }
- }
- }
-
- // Overwrite connection URL parameters with code provided parameters
- // if applicable
- if (props != null) {
- // Copy across normalizing keys to lower case in the English Locale
- for (Entry<Object, Object> e : props.entrySet()) {
- ps.put(e.getKey().toString().toLowerCase(Locale.ENGLISH), e.getValue());
- }
- }
+ // Compute the effective properties
+ Properties ps = this.getEffectiveProperties(url, props);
// Figure out desired JDBC compatibility level
int compatibilityLevel = JdbcCompatibility.parseLevel(ps.get(PARAM_JDBC_COMPATIBILITY));
@@ -356,6 +300,111 @@ public abstract class JenaDriver impleme
}
/**
+ * Determines the effective properties
+ * <p>
+ * This method parses the connection URL for properties and then
+ * appends/overwrites properties from the given {@link Properties} object as
+ * appropriate
+ * </p>
+ *
+ * @param url
+ * Connection URL
+ * @param props
+ * Properties
+ * @return Effective Properties
+ */
+ @SuppressWarnings("unchecked")
+ private Properties getEffectiveProperties(String url, Properties props) {
+ // Create new empty properties
+ Properties ps = new Properties();
+
+ // Parse out the key value pairs from the connection URL
+ url = url.substring(DRIVER_PREFIX.length() + this.implPrefix.length());
+ String[] kvps = url.split("&|;");
+ for (int i = 0; i < kvps.length; i++) {
+ String kvp = kvps[i];
+ if (kvp.length() == 0)
+ continue;
+
+ // Try to split into key and value
+ String key, value;
+ if (kvp.contains("=")) {
+ String[] temp = kvp.split("=", 2);
+ key = temp[0];
+ value = temp[1];
+ } else {
+ key = kvp;
+ value = null;
+ }
+
+ // All keys are normalized to lower case using the English Locale
+ key = key.toLowerCase(Locale.ENGLISH);
+
+ // Put into properties appropriately
+ if (!ps.containsKey(key)) {
+ // Doesn't yet exist, add a string/list as appropriate
+ if (this.allowsMultipleValues(key)) {
+ List<String> values = new ArrayList<String>();
+ values.add(value);
+ ps.put(key, values);
+ } else {
+ ps.put(key, value);
+ }
+ } else if (this.allowsMultipleValues(key)) {
+ // If it allows multiple values append to those existing
+ Object currValue = ps.get(key);
+ if (currValue instanceof List<?>) {
+ // Can just append to existing list
+ ((List<Object>) currValue).add(value);
+ } else {
+ // Convert to list
+ List<String> values = new ArrayList<String>();
+ values.add(currValue.toString());
+ values.add(value);
+ ps.put(key, values);
+ }
+ }
+ }
+
+ // Overwrite connection URL parameters with code provided parameters
+ // if applicable
+ if (props != null) {
+ // Copy across normalizing keys to lower case in the English Locale
+ for (Entry<Object, Object> e : props.entrySet()) {
+ String key = e.getKey().toString().toLowerCase(Locale.ENGLISH);
+ Object value = e.getValue();
+
+ if (ps.containsKey(key)) {
+ // Already exists in connection URL so append/overwrite as
+ // appropriate
+ if (this.allowsMultipleValues(key)) {
+ // Should append to existing values
+ Object currValue = ps.get(key);
+ if (currValue instanceof List<?>) {
+ // Can just append to existing list
+ ((List<Object>) currValue).add(value);
+ } else {
+ // Convert to list
+ List<String> values = new ArrayList<String>();
+ values.add(currValue.toString());
+ values.add(value.toString());
+ ps.put(key, values);
+ }
+ } else {
+ // Overwrite existing value
+ ps.put(key, value);
+ }
+ } else {
+ // Not in connection URL so add key value pair
+ ps.put(key, value);
+ }
+ }
+ }
+
+ return ps;
+ }
+
+ /**
* Gets whether a parameter is allowed to have multiple values
* <p>
* If you override this method in your driver implementation you should make
@@ -407,12 +456,63 @@ public abstract class JenaDriver impleme
return this.majorVer;
}
- public DriverPropertyInfo[] getPropertyInfo(String arg0, Properties arg1) throws SQLException {
- // TODO: Make abstract and force implementations to implement
- return new DriverPropertyInfo[0];
+ public final DriverPropertyInfo[] getPropertyInfo(String url, Properties props) throws SQLException {
+ Properties ps = this.getEffectiveProperties(url, props);
+
+ // Create base driver properties
+ List<DriverPropertyInfo> baseProps = new ArrayList<DriverPropertyInfo>();
+
+ // JDBC compatibility level
+ DriverPropertyInfo jdbcCompatLevel = new DriverPropertyInfo(PARAM_JDBC_COMPATIBILITY, ps.getProperty(
+ PARAM_JDBC_COMPATIBILITY, Integer.toString(JdbcCompatibility.DEFAULT)));
+ jdbcCompatLevel.description = "Configures how compatible the driver will attempt to be with JDBC, primarily affects reported column types for result sets";
+ jdbcCompatLevel.required = false;
+ String[] choices = new String[9];
+ for (int i = 0; i < choices.length; i++) {
+ choices[i] = Integer.toString(i + 1);
+ }
+ jdbcCompatLevel.choices = choices;
+ baseProps.add(jdbcCompatLevel);
+
+ // Pre-processors
+ DriverPropertyInfo preProcessor = new DriverPropertyInfo(PARAM_PRE_PROCESSOR, StrUtils.strjoin(",",
+ this.getValues(ps, PARAM_PRE_PROCESSOR)));
+ preProcessor.description = "Configures pre-processors which are used to amend SPARQL text, queries or updates before these are passed to the underlying SPARQL engine, multiple fully qualified class names may be specified";
+ preProcessor.required = false;
+ baseProps.add(preProcessor);
+
+ // Have the derived implementation create the final property information
+ return this.getPropertyInfo(ps, baseProps);
+ }
+
+ /**
+ * Helper method for copying the base properties into the final properties
+ *
+ * @param finalProps
+ * Final Properties array
+ * @param baseProps
+ * Base Properties
+ * @param start
+ * Index in the final properties array at which to start copying
+ */
+ protected final void copyBaseProperties(DriverPropertyInfo[] finalProps, List<DriverPropertyInfo> baseProps, int start) {
+ for (int i = start, j = 0; i < finalProps.length && j < baseProps.size(); i++, j++) {
+ finalProps[i] = baseProps.get(j);
+ }
}
/**
+ * Gets driver property information to aid in making a connection
+ *
+ * @param connProps
+ * Known connection properties
+ * @param baseDriverProps
+ * Base driver properties supported by the driver
+ * @return Driver property information
+ */
+ protected abstract DriverPropertyInfo[] getPropertyInfo(Properties connProps, List<DriverPropertyInfo> baseDriverProps);
+
+ /**
* Returns that a Jena JDBC driver is not JDBC compliant since strict JDBC
* compliance requires support for SQL-92 and since we are using SPARQL we
* don't meet that criteria
@@ -452,4 +552,48 @@ public abstract class JenaDriver impleme
}
}
+ /**
+ * Gets whether a given property is set to true
+ *
+ * @param props
+ * Properties
+ * @param key
+ * Key
+ * @return True if the key is set to a non-null value whose lower case
+ * string equals {@code true}, otherwise false
+ */
+ protected boolean isTrue(Properties props, String key) {
+ Object obj = props.get(key);
+ if (obj == null)
+ return false;
+ String value = obj.toString().toLowerCase(Locale.ENGLISH);
+ return "true".equals(value);
+ }
+
+ /**
+ * Gets whether a given property is set to a specific value
+ * <p>
+ * Applies {@link String#trim()} and {@link String#toLowerCase(Locale)} to
+ * the set value before comparing it with the expected value
+ * </p>
+ *
+ * @param props
+ * Properties
+ * @param key
+ * Key
+ * @param value
+ * Expected value
+ * @return True if the key is set to a value which matches the expected
+ * value, otherwise false
+ */
+ protected boolean isSetToValue(Properties props, String key, String value) {
+ Object obj = props.get(key);
+ if (obj == null)
+ return value == null;
+ if (value == null)
+ return false;
+ String actualValue = obj.toString().trim().toLowerCase(Locale.ENGLISH);
+ return value.equals(actualValue);
+ }
+
}
Modified: jena/Experimental/jena-jdbc/jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/MemDriver.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/MemDriver.java?rev=1471789&r1=1471788&r2=1471789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/MemDriver.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-driver-mem/src/main/java/org/apache/jena/jdbc/mem/MemDriver.java Thu Apr 25 00:00:12 2013
@@ -19,7 +19,9 @@
package org.apache.jena.jdbc.mem;
import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
+import java.util.List;
import java.util.Properties;
import org.apache.jena.jdbc.JenaDriver;
@@ -94,14 +96,14 @@ public class MemDriver extends JenaDrive
protected JenaConnection connect(Properties props, int compatibilityLevel) throws SQLException {
Object dsObj = props.get(PARAM_DATASET);
String empty = props.getProperty(PARAM_EMPTY);
- if (empty != null) empty = empty.toLowerCase();
- if (dsObj == null && empty == null) throw new SQLException("Neither one of the " + PARAM_DATASET + " or " + PARAM_EMPTY + " connection parameters is not present in the JDBC Connection URL or the provided Properties object");
+ if (dsObj == null && empty == null) throw new SQLException("Neither one of the " + PARAM_DATASET + " or " + PARAM_EMPTY + " connection parameters is present in the JDBC Connection URL or the provided Properties object");
if (dsObj != null) {
if (dsObj instanceof Dataset) {
// Dataset provided directly
return new MemConnection((Dataset)dsObj, JenaConnection.DEFAULT_HOLDABILITY, JenaConnection.DEFAULT_AUTO_COMMIT, JenaConnection.DEFAULT_ISOLATION_LEVEL, compatibilityLevel);
} else {
+ // Load dataset from a file
try {
Dataset ds = DatasetFactory.createMem();
RDFDataMgr.read(ds, dsObj.toString());
@@ -110,11 +112,53 @@ public class MemDriver extends JenaDrive
throw new SQLException("Error occurred while reading from the specified RDF dataset file - " + dsObj.toString(), e);
}
}
- } else if ("true".equals(empty)) {
+ } else if (this.isTrue(props, PARAM_EMPTY)) {
+ // Use an empty dataset
return new MemConnection(DatasetFactory.createMem(), JenaConnection.DEFAULT_HOLDABILITY, JenaConnection.DEFAULT_AUTO_COMMIT, JenaConnection.DEFAULT_ISOLATION_LEVEL, compatibilityLevel);
} else {
throw new SQLException("Insufficient parameters to create a Jena JDBC in-memory connection, please supply a Dataset file/instance via the " + PARAM_DATASET + " parameter or supply " + PARAM_EMPTY + "=true to connect to a new empty dataset");
}
}
+ @Override
+ protected DriverPropertyInfo[] getPropertyInfo(Properties connProps, List<DriverPropertyInfo> baseDriverProps) {
+ DriverPropertyInfo[] driverProps;
+ if (connProps.containsKey(PARAM_DATASET) || !this.isTrue(connProps, PARAM_EMPTY)) {
+ driverProps = new DriverPropertyInfo[1 + baseDriverProps.size()];
+
+ // Dataset parameter
+ driverProps[0] = new DriverPropertyInfo(PARAM_DATASET, connProps.getProperty(PARAM_DATASET));
+ driverProps[0].required = true;
+ driverProps[0].description = "Sets a path to a file that should be read in to form an in-memory dataset";
+
+ this.copyBaseProperties(driverProps, baseDriverProps, 1);
+ } else if (connProps.containsKey(PARAM_EMPTY)) {
+ driverProps = new DriverPropertyInfo[1 + baseDriverProps.size()];
+
+ // Empty parameter
+ driverProps[0] = new DriverPropertyInfo(PARAM_EMPTY, connProps.getProperty(PARAM_EMPTY));
+ driverProps[0].required = true;
+ driverProps[0].choices = new String[] { "true", "false" };
+ driverProps[0].description = "Sets that the driver will use an empty in-memory dataset as the initial dataset, when set to true the " + PARAM_DATASET + " parameter is not required";
+
+ this.copyBaseProperties(driverProps, baseDriverProps, 1);
+ } else {
+ driverProps = new DriverPropertyInfo[2 + baseDriverProps.size()];
+
+ // Dataset parameter
+ driverProps[0] = new DriverPropertyInfo(PARAM_DATASET, connProps.getProperty(PARAM_DATASET));
+ driverProps[0].required = true;
+ driverProps[0].description = "Sets a path to a file that should be read in to form an in-memory dataset";
+
+ // Empty parameter
+ driverProps[1] = new DriverPropertyInfo(PARAM_EMPTY, connProps.getProperty(PARAM_EMPTY));
+ driverProps[1].required = false;
+ driverProps[1].choices = new String[] { "true", "false" };
+ driverProps[1].description = "Sets that the driver will use an empty in-memory dataset as the initial dataset, when set to true the " + PARAM_DATASET + " parameter is not required";
+
+ copyBaseProperties(driverProps, baseDriverProps, 2);
+ }
+ return driverProps;
+ }
+
}
Modified: jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/RemoteEndpointDriver.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/RemoteEndpointDriver.java?rev=1471789&r1=1471788&r2=1471789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/RemoteEndpointDriver.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/RemoteEndpointDriver.java Thu Apr 25 00:00:12 2013
@@ -19,6 +19,7 @@
package org.apache.jena.jdbc.remote;
import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
@@ -176,4 +177,40 @@ public class RemoteEndpointDriver extend
return super.allowsMultipleValues(key);
}
}
+
+ @Override
+ protected DriverPropertyInfo[] getPropertyInfo(Properties connProps, List<DriverPropertyInfo> baseDriverProps) {
+ DriverPropertyInfo[] driverProps = new DriverPropertyInfo[8 + baseDriverProps.size()];
+ this.copyBaseProperties(driverProps, baseDriverProps, 8);
+
+ // Query Endpoint parameter
+ driverProps[0] = new DriverPropertyInfo(PARAM_QUERY_ENDPOINT, connProps.getProperty(PARAM_QUERY_ENDPOINT));
+ driverProps[0].required = !connProps.containsKey(PARAM_UPDATE_ENDPOINT);
+ driverProps[0].description = "Sets the SPARQL Query endpoint to use for query operations, if this is specified and " + PARAM_UPDATE_ENDPOINT + " is not then a read-only connection will be created";
+
+ // Update Endpoint parameter
+ driverProps[1] = new DriverPropertyInfo(PARAM_UPDATE_ENDPOINT, connProps.getProperty(PARAM_UPDATE_ENDPOINT));
+ driverProps[1].required = !connProps.containsKey(PARAM_UPDATE_ENDPOINT);
+ driverProps[1].description = "Sets the SPARQL Update endpoint to use for update operations, if this is specified and " + PARAM_QUERY_ENDPOINT + " is not then a write-only connection will be created";
+
+ // Default Graph parameter
+ driverProps[2] = new DriverPropertyInfo(PARAM_DEFAULT_GRAPH_URI, null);
+
+ // Named Graph parameter
+ driverProps[3] = new DriverPropertyInfo(PARAM_NAMED_GRAPH_URI, null);
+
+ // Using Graph parameter
+ driverProps[4] = new DriverPropertyInfo(PARAM_USING_GRAPH_URI, null);
+
+ // Using Named Graph parameter
+ driverProps[5] = new DriverPropertyInfo(PARAM_USING_NAMED_GRAPH_URI, null);
+
+ // User Name parameter
+ driverProps[6] = new DriverPropertyInfo(PARAM_USERNAME, connProps.getProperty(PARAM_USERNAME));
+
+ // Password parameter
+ driverProps[7] = new DriverPropertyInfo(PARAM_PASSWORD, connProps.getProperty(PARAM_PASSWORD));
+
+ return driverProps;
+ }
}
Modified: jena/Experimental/jena-jdbc/jena-jdbc-driver-tdb/src/main/java/org/apache/jena/jdbc/tdb/TDBDriver.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-driver-tdb/src/main/java/org/apache/jena/jdbc/tdb/TDBDriver.java?rev=1471789&r1=1471788&r2=1471789&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-driver-tdb/src/main/java/org/apache/jena/jdbc/tdb/TDBDriver.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-driver-tdb/src/main/java/org/apache/jena/jdbc/tdb/TDBDriver.java Thu Apr 25 00:00:12 2013
@@ -19,7 +19,9 @@
package org.apache.jena.jdbc.tdb;
import java.io.File;
+import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
+import java.util.List;
import java.util.Properties;
import org.apache.jena.jdbc.JenaDriver;
@@ -100,7 +102,7 @@ public class TDBDriver extends JenaDrive
+ " is not present in the connection URL or the provided Properties object");
// Determine location
- boolean useMem = location.trim().toLowerCase().equals(LOCATION_MEM);
+ boolean useMem = this.isSetToValue(props, PARAM_LOCATION, LOCATION_MEM);
File loc = new File(location);
if (useMem) {
LOGGER.warn("TDB Driver connection string specifies use of a pure in-memory dataset, this is not recommended for anything other than basic testing");
@@ -114,8 +116,7 @@ public class TDBDriver extends JenaDrive
}
// Validate location if required
- String mustExist = props.getProperty(PARAM_MUST_EXIST, "false").toLowerCase();
- if ("true".equals(mustExist) && !useMem) {
+ if (this.isTrue(props, PARAM_MUST_EXIST) && !useMem) {
if (!loc.exists()) {
throw new SQLException("TDB Driver connection string specifies location " + loc.getAbsolutePath()
+ " which does not exist, correct the " + PARAM_LOCATION + " parameter or set the " + PARAM_MUST_EXIST
@@ -140,4 +141,23 @@ public class TDBDriver extends JenaDrive
}
}
+ @Override
+ protected DriverPropertyInfo[] getPropertyInfo(Properties connProps, List<DriverPropertyInfo> baseDriverProps) {
+ DriverPropertyInfo[] driverProps = new DriverPropertyInfo[2 + baseDriverProps.size()];
+ this.copyBaseProperties(driverProps, baseDriverProps, 2);
+
+ // Location parameter
+ driverProps[0] = new DriverPropertyInfo(PARAM_LOCATION, connProps.getProperty(PARAM_LOCATION));
+ driverProps[0].required = true;
+ driverProps[0].description = "Sets the location of a TDB dataset, should be a file system path. The value " + LOCATION_MEM + " may be used for a non-persistent in-memory dataset but this should only be used for testing";
+
+ // Must Exist parameter
+ driverProps[1] = new DriverPropertyInfo(PARAM_MUST_EXIST, connProps.getProperty(PARAM_MUST_EXIST));
+ driverProps[1].required = false;
+ driverProps[1].choices = new String[] { "true", "false" };
+ driverProps[1].description = "If set to true requests that the driver check whether the " + PARAM_LOCATION + " parameter refers to an existing location before establishing a connection";
+
+ return driverProps;
+ }
+
}