You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by en...@apache.org on 2013/09/10 12:38:53 UTC
svn commit: r1521431 [1/2] - in /clerezza/trunk/clerezza-virtuoso: ./
ext.virtuoso.jdbc/ ext.virtuoso.jdbc/src/ ext.virtuoso.jdbc/src/main/
ext.virtuoso.jdbc/src/main/resources/
ext.virtuoso.jdbc/src/main/resources/maven/ ext.virtuoso.jdbc/src/main/res...
Author: enridaga
Date: Tue Sep 10 10:38:51 2013
New Revision: 1521431
URL: http://svn.apache.org/r1521431
Log:
CLEREZZA-811 Initial commit
Added:
clerezza/trunk/clerezza-virtuoso/README.md
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml (with props)
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar (with props)
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom (with props)
clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml (with props)
clerezza/trunk/clerezza-virtuoso/pom.xml (with props)
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml (with props)
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/access/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/access/VirtuosoWeightedProviderTest.java
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/resources/
clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/resources/log4j.properties
Modified:
clerezza/trunk/clerezza-virtuoso/ (props changed)
Propchange: clerezza/trunk/clerezza-virtuoso/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Sep 10 10:38:51 2013
@@ -0,0 +1 @@
+target
Added: clerezza/trunk/clerezza-virtuoso/README.md
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/README.md?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/README.md (added)
+++ clerezza/trunk/clerezza-virtuoso/README.md Tue Sep 10 10:38:51 2013
@@ -0,0 +1,54 @@
+# Virtuoso/Clerezza storage adapter
+
+This is an implementation of the storage API of Clerezza[1] to use Virtuoso as storage.
+
+
+## Build and Install
+To build this project you need Maven.
+
+### Simple build
+From the main folder:
+
+ $ mvn clean install
+
+Results will be 2 bundles:
+
+* ext.virtuoso.jdbc : contains JDBC drivers form Virtuoso
+* rdf.virtuoso.storage : contains the implementation of the clerezza storage API for Virtuoso
+
+Bundles are in the /target folders:
+
+* ext.virtuoso.jdbc/target/ext.virtuoso.jdbc-<version>.jar
+* rdf.virtuoso.storage/target/rdf.virtuoso.storage-<version>.jar
+
+### Build forcing tests
+You must have a Virtuoso running server to do tests.
+To activate tests, you must execute maven with the virtuoso-do-tests profile, for example:
+
+ $ mvn test -Pvirtuoso-do-tests
+
+By default, the tests will use the parameters configured in the pom.xml. Change the parameters' values to the ones that fit your installation of Virtuoso.
+
+You can configure the following parameters:
+
+* virtuoso.test (default is null, sets to true if you activate the 'virtuoso-do-tests' profile)
+* virtuoso.driver (default is 'virtuoso.jdbc4.Driver')
+* virtuoso.host (default is 'localhost')
+* virtuoso.port (default is '1111')
+* virtuoso.user (default is 'dba')
+* virtuoso.password (default is 'dba')
+
+To override them from cli, you can also do the following:
+
+ $ mvn test -Pvirtuoso-do-tests -DargLine="-Dvirtuoso.password=mypassword -Dvirtuoso.port=1234"
+
+
+### Hot deploy on a Clerezza or Stanbol[2] running servers
+
+To deploy the bundles in a running Sling instance you can do:
+
+ $ mvn install -PinstallBundle -Dsling.url=http://localhost:8080/system/console (change this to be the actual server admin interface)
+
+
+* [1] http://incubator.apache.org/clerezza/
+* [2] http://incubator.apache.org/stanbol/
\ No newline at end of file
Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml
------------------------------------------------------------------------------
svn:mime-type = application/xml
Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar
------------------------------------------------------------------------------
svn:mime-type = application/jar
Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom
------------------------------------------------------------------------------
svn:mime-type = application/xml
Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml
------------------------------------------------------------------------------
svn:mime-type = application/xml
Added: clerezza/trunk/clerezza-virtuoso/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/pom.xml
------------------------------------------------------------------------------
svn:mime-type = application/xml
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md Tue Sep 10 10:38:51 2013
@@ -0,0 +1,3 @@
+# Virtuoso Storage bindings for Clerezza
+
+See the README.md in ../
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.
Propchange: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml
------------------------------------------------------------------------------
svn:mime-type = application/xml
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,75 @@
+package rdf.virtuoso.storage;
+
+import java.util.Collection;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+/**
+ * This is a read-only version of {@link VirtuosoMGraph}
+ * @author enridaga
+ *
+ */
+public class VirtuosoGraph extends VirtuosoMGraph implements Graph{
+
+ /**
+ * Logger
+ */
+ protected Logger logger = LoggerFactory
+ .getLogger(VirtuosoGraph.class);
+
+ public VirtuosoGraph(String name, VirtuosoConnection connection) {
+ super(name, connection);
+ }
+
+ @Override
+ public synchronized boolean add(Triple e) {
+ logger.warn("Attempting modifying an immutable graph");
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized boolean addAll(Collection<? extends Triple> c) {
+ logger.warn("Attempting modifying an immutable graph");
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized void clear() {
+ logger.warn("Attempting modifying an immutable graph");
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized boolean remove(Object o) {
+ logger.warn("Attempting modifying an immutable graph");
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized boolean removeAll(Collection<?> col) {
+ logger.warn("Attempting modifying an immutable graph");
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Must be a VirtuosoGraph with the same name.
+ */
+ @Override
+ public boolean equals(Object o) {
+ logger.debug("equals({})",o.getClass());
+ if (o instanceof VirtuosoGraph) {
+ logger.debug("{} is a VirtuosoGraph)",o);
+ if (((VirtuosoGraph) o).getName().equals(this.getName())) {
+ logger.debug("Names are equal! They are equal!");
+ return true;
+ }
+ }else{
+ logger.debug("Not a VirtuosoGraph instance: {}",o.getClass());
+ }
+ return false;
+ }
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,646 @@
+package rdf.virtuoso.storage;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Language;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.TypedLiteral;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.LockableMGraph;
+import org.apache.clerezza.rdf.core.impl.AbstractMGraph;
+import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
+import org.apache.clerezza.rdf.core.impl.TypedLiteralImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wymiwyg.commons.util.collections.BidiMap;
+import org.wymiwyg.commons.util.collections.BidiMapImpl;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+import virtuoso.jdbc4.VirtuosoExtendedString;
+import virtuoso.jdbc4.VirtuosoRdfBox;
+import virtuoso.jdbc4.VirtuosoResultSet;
+
+/**
+ * Implementation of MGraph for the Virtuoso quad store.
+ *
+ * @author enridaga
+ *
+ */
+public class VirtuosoMGraph extends AbstractMGraph implements MGraph,
+ LockableMGraph {
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ private final Lock readLock = lock.readLock();
+ private final Lock writeLock = lock.writeLock();
+
+ /**
+ * Bidirectional map for managing the conversion from virtuoso blank nodes
+ * (strings) to clerezza blank nodes and vice versa.
+ */
+ private final BidiMap<String, BNode> bnodesMap;
+ private int maxVirtBnodeIndex = 0;
+
+ /**
+ * Logger
+ */
+ protected Logger logger = LoggerFactory.getLogger(VirtuosoMGraph.class);
+
+ /**
+ * Connection
+ */
+ private VirtuosoConnection connection = null;
+ /**
+ * The name of the graph
+ */
+ private String name = null;
+ private int size = 0;
+
+ private VirtuosoGraph readOnly = null;
+
+ /**
+ * Creates a {@link VirtuosoMGraph} Virtuoso MGraph binds directly to the
+ * store.
+ *
+ * @param connection
+ */
+ public VirtuosoMGraph(String name, VirtuosoConnection connection) {
+ logger.debug("VirtuosoMGraph(String {}, VirtuosoConnection {})", name,
+ connection);
+ this.name = name;
+ this.connection = connection;
+ this.bnodesMap = new BidiMapImpl<String, BNode>();
+ }
+
+ /**
+ * Gets the connection
+ *
+ * @return
+ */
+ protected VirtuosoConnection getConnection() {
+ logger.debug("getConnection()");
+ return this.connection;
+ }
+
+ @Override
+ public ReadWriteLock getLock() {
+ logger.debug("getLock()");
+ return lock;
+ }
+
+ @Override
+ public Graph getGraph() {
+ logger.debug("getGraph()");
+ return asVirtuosoGraph();
+ }
+
+ public VirtuosoGraph asVirtuosoGraph() {
+ logger.debug("asVirtuosoGraph()");
+ if (this.readOnly == null) {
+ logger.debug("create embedded singleton read-only instance");
+ this.readOnly = new VirtuosoGraph(name, connection);
+ }
+ return readOnly;
+ }
+
+ @Override
+ protected Iterator<Triple> performFilter(NonLiteral subject,
+ UriRef predicate, Resource object) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("performFilter(NonLiteral s, UriRef p, Resource o)");
+ logger.debug(" > s: {}", subject);
+ logger.debug(" > p: {}", predicate);
+ logger.debug(" > o: {}", object);
+ }
+ StringBuilder sb = new StringBuilder();
+ String virtSubject = toVirtSubject(subject);
+ String virtPredicate = toVirtPredicate(predicate);
+ String virtObject = toVirtObject(object);
+ sb.append("SPARQL SELECT ?SUBJECT ?PREDICATE ?OBJECT WHERE { GRAPH <")
+ .append(this.getName()).append("> { ")
+ .append(" ?SUBJECT ?PREDICATE ?OBJECT ");
+ if (virtSubject != null) {
+ sb.append(". FILTER( ").append("?SUBJECT = ").append(virtSubject)
+ .append(") ");
+ }
+ if (virtPredicate != null) {
+ sb.append(". FILTER( ").append("?PREDICATE = ")
+ .append(virtPredicate).append(") ");
+ }
+ if (virtObject != null) {
+ sb.append(". FILTER( ").append("?OBJECT = ").append(virtObject)
+ .append(") ");
+ }
+ sb.append(" } } ");
+
+ String sql = sb.toString();
+ logger.debug("Executing SQL: {}", sql);
+ Statement st;
+ try {
+ readLock.lock();
+ st = connection.createStatement();
+ boolean has = st.execute(sql);
+ final VirtuosoResultSet rs = (VirtuosoResultSet) st.getResultSet();
+ readLock.unlock();
+ return new Iterator<Triple>() {
+ Triple current = null;
+ private boolean didNext = false;
+ private boolean hasNext = false;
+
+ @Override
+ public boolean hasNext() {
+ readLock.lock();
+ try {
+ if (!didNext) {
+ hasNext = rs.next();
+ didNext = true;
+ }
+ return hasNext;
+ } catch (SQLException e) {
+ logger.error("Error while iterating results", e);
+ return false;
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Triple next() {
+ try {
+ readLock.lock();
+ if (!didNext) {
+ rs.next();
+ }
+ didNext = false;
+ current = new TripleBuilder(rs.getObject(1),
+ rs.getObject(2), rs.getObject(3)).build();
+ } catch (VirtuosoException e) {
+ logger.error("Error while iterating results", e);
+ } finally {
+ readLock.unlock();
+ }
+ return current;
+ }
+
+ @Override
+ public void remove() {
+ writeLock.lock();
+ try {
+ if (current == null) {
+ throw new IllegalStateException();
+ }
+ VirtuosoMGraph.this.performRemove(current);
+ current = null;
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ };
+ } catch (VirtuosoException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ } catch (SQLException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * We load the size every time it is requested.
+ */
+ @Override
+ public int size() {
+ logger.debug("size()");
+ loadSize();
+ return this.size;
+ }
+
+ @Override
+ public void clear() {
+ logger.debug("clear()");
+ String SQL = "SPARQL CLEAR GRAPH <" + this.getName() + ">";
+ this.writeLock.lock();
+ try {
+ logger.debug("Executing SQL: {}", SQL);
+ Statement st = getConnection().createStatement();
+ boolean success = st.execute(SQL);
+ if (success) {
+ this.size = 0;
+ } else {
+ throw new RuntimeException(
+ "Problems on clear() method. Cannot clear the graph!");
+ }
+ } catch (VirtuosoException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ } catch (SQLException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ } finally {
+ this.writeLock.unlock();
+ }
+ }
+
+ private void loadSize() {
+ logger.debug("loadSize()");
+ String SQL = "SPARQL SELECT COUNT(*) FROM <" + this.getName()
+ + "> WHERE { ?s ?p ?o } ";
+ int size = 0;
+ this.readLock.lock();
+ try {
+ logger.debug("Executing SQL: {}", SQL);
+ Statement st = getConnection().createStatement();
+ VirtuosoResultSet rs = (VirtuosoResultSet) st.executeQuery(SQL);
+ rs.next();
+ size = rs.getInt(1);
+ } catch (VirtuosoException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ } catch (SQLException e) {
+ logger.error("ERROR while executing statement", e);
+ throw new RuntimeException(e);
+ } finally {
+ this.readLock.unlock();
+ }
+ this.size = size;
+ }
+
+ protected boolean performAdd(Triple triple) {
+ return add(triple, connection);
+ }
+
+ protected boolean performRemove(Triple triple) {
+ return remove(triple, connection);
+ }
+
+ /**
+ * Adds a triple in the store
+ *
+ * @param triple
+ * @param connection
+ * @return
+ */
+ private boolean add(Triple triple, VirtuosoConnection connection) {
+ logger.debug("add(Triple {}, VirtuosoConnection {})", triple,
+ connection);
+ String sql = getAddSQLStatement(triple);
+ logger.debug("Executing SQL: {}", sql);
+ writeLock.lock();
+ try {
+ Statement st = connection.createStatement();
+ st.execute(sql);
+ } catch (VirtuosoException e) {
+ logger.error("ERROR while executing statement", e);
+ return false;
+ } catch (SQLException e) {
+ logger.error("ERROR while executing statement", e);
+ return false;
+ } finally {
+ writeLock.unlock();
+ }
+ return true;
+ }
+
+ /**
+ * Removes a triple from the store.
+ *
+ * @param triple
+ * @param connection
+ * @return
+ */
+ private boolean remove(Triple triple, VirtuosoConnection connection) {
+ logger.debug("remove(Triple triple, VirtuosoConnection connection)",
+ triple, connection);
+ String sql = getRemoveSQLStatement(triple);
+ logger.debug("Executing SQL: {}", sql);
+ writeLock.lock();
+ try {
+ Statement st = connection.createStatement();
+ st.execute(sql);
+ } catch (SQLException e) {
+ logger.error("ERROR while executing statement", e);
+ return false;
+ } finally {
+ writeLock.unlock();
+ }
+ return true;
+ }
+
+ /**
+ * Returns the graph name
+ *
+ * @return
+ */
+ public String getName() {
+ logger.debug("getName()");
+ return name;
+ }
+
+ /**
+ * Get the clerezza BNode corresponding to the given String from a Virtuoso
+ * resultset.
+ *
+ * @param virtbnode
+ * @return
+ */
+ private BNode toBNode(String virtbnode) {
+ logger.debug("toBNode(String {})", virtbnode);
+ BNode bnode = bnodesMap.get(virtbnode);
+ if (bnode == null) {
+ bnode = new BNode();
+ bnodesMap.put(virtbnode, bnode);
+ }
+ // Subject is BNode
+ return bnode;
+ }
+
+ /**
+ * Generate a new local bnode to be used in virtuoso queries
+ *
+ * @return
+ */
+ private String nextVirtBnode() {
+ logger.debug("nextVirtBnode()");
+ maxVirtBnodeIndex++;
+ return new StringBuilder().append("_:b").append(maxVirtBnodeIndex)
+ .toString();
+ }
+
+ /**
+ *
+ * @param bnode
+ * @return
+ */
+ private String toVirtBnode(BNode bnode) {
+ logger.debug("toVirtBnode(BNode {})", bnode);
+ String virtBnode = bnodesMap.getKey(bnode);
+ if (virtBnode == null) {
+ // We create a local bnode mapped to the BNode given
+ virtBnode = nextVirtBnode();
+ bnodesMap.put(virtBnode, bnode);
+ }
+ return virtBnode;
+ }
+
+ private String getAddSQLStatement(Triple triple) {
+ logger.debug("getAddSQLStatement(Triple {})", triple);
+ StringBuilder sb = new StringBuilder();
+ String subject = toVirtSubject(triple.getSubject());
+ String predicate = toVirtPredicate(triple.getPredicate());
+ String object = toVirtObject(triple.getObject());
+ String sql = sb.append("SPARQL INSERT INTO <").append(this.getName())
+ .append("> { ").append(subject).append(" ").append(predicate)
+ .append(" ").append(object).append(" }").toString();
+ return sql;
+ }
+
+ private String getRemoveSQLStatement(Triple triple) {
+ logger.debug("getRemoveSQLStatement(Triple {})", triple);
+ StringBuilder sb = new StringBuilder();
+ String subject = toVirtSubject(triple.getSubject());
+ String predicate = toVirtPredicate(triple.getPredicate());
+ String object = toVirtObject(triple.getObject());
+ String sql = sb.append("SPARQL DELETE FROM <").append(this.getName())
+ .append("> { ").append(subject).append(" ").append(predicate)
+ .append(" ").append(object).append(" } FROM <")
+ .append(this.getName()).append("> ").append(" WHERE { ")
+ .append(subject).append(" ").append(predicate).append(" ")
+ .append(object).append(" }").toString();
+ return sql;
+ }
+
+ /**
+ * Returns a string to be used in SQL statements as Object of a triple.
+ *
+ * @param object
+ * @return
+ */
+ private String toVirtObject(Resource object) {
+ logger.debug("toVirtObject(Resource {})", object);
+ if (object == null)
+ return null;
+ if (object instanceof UriRef) {
+ return toVirtIri((UriRef) object);
+ } else if (object instanceof BNode) {
+ return toVirtBnode((BNode) object);
+ } else if (object instanceof PlainLiteral) {
+ return toVirtPlainLiteral((PlainLiteral) object);
+ } else if (object instanceof TypedLiteral) {
+ return toVirtTypedLiteral((TypedLiteral) object);
+ }
+ return null;
+ }
+
+ /**
+ * Returns a string to be used in SQL statements.
+ *
+ * @param object
+ * @return
+ */
+ private String toVirtTypedLiteral(TypedLiteral object) {
+ logger.debug("toVirtTypedLiteral(TypedLiteral {})", object);
+ UriRef dt = object.getDataType();
+ String literal = object.getLexicalForm();
+ return new StringBuilder().append('"').append(literal).append('"')
+ .append("^^").append(toVirtIri(dt)).toString();
+ }
+
+ /**
+ * Returns a string to be used in SQL statements.
+ *
+ * @param object
+ * @return
+ */
+ private String toVirtPlainLiteral(PlainLiteral object) {
+ logger.debug("toVirtPlainLiteral(PlainLiteral {})", object);
+ Language lang = object.getLanguage();
+ String literal = object.getLexicalForm();
+ StringBuilder sb = new StringBuilder().append('"').append(literal)
+ .append('"');
+ if (lang == null) {
+ return sb.toString();
+ } else {
+ return sb.append("@").append(lang).toString();
+ }
+ }
+
+ /**
+ * Returns a string to be used in SQL statements as Predicate of a triple.
+ *
+ * @param predicate
+ * @return
+ */
+ private String toVirtPredicate(UriRef predicate) {
+ logger.debug("toVirtPredicate(UriRef {}) ", predicate);
+ if (predicate == null)
+ return null;
+ return toVirtIri(predicate);
+ }
+
+ private String toVirtIri(UriRef ur) {
+ logger.debug("toVirtIri(UriRef {})", ur);
+ return "<" + ur.getUnicodeString() + ">";
+ }
+
+ /**
+ * Returns a string to be used in SQL statements as Subject of a triple.
+ *
+ * @param subject
+ * @return
+ */
+ private String toVirtSubject(NonLiteral subject) {
+ logger.debug("toVirtSubject(NonLiteral {})", subject);
+ if (subject == null) {
+ return null;
+ }
+ if (subject instanceof UriRef) {
+ return toVirtIri((UriRef) subject);
+ } else if (subject instanceof BNode) {
+ return toVirtBnode((BNode) subject);
+ } else {
+ // These should be the only 2 implementations
+ throw new IllegalArgumentException(
+ "subject must be BNode or UriRef");
+ }
+ }
+
+ /**
+ * Builds a clerezza Triple from Virtuoso result types
+ *
+ */
+ private class TripleBuilder {
+
+ Object s = null;
+ Object p = null;
+ Object o = null;
+
+ public TripleBuilder(Object s, Object p, Object o) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("TripleBuilder(Object s, Object p, Object o)");
+ logger.debug("> s: {}", s);
+ logger.debug("> p: {}", p);
+ logger.debug("> o: {}", o);
+ }
+ this.s = s;
+ this.p = p;
+ this.o = o;
+ }
+
+ public Triple build() {
+ logger.debug("TripleBuilder.build()");
+ return new Triple() {
+ @Override
+ public NonLiteral getSubject() {
+ logger.debug("TripleBuilder.getSubject() : {}", s);
+ if (s instanceof VirtuosoExtendedString) {
+ VirtuosoExtendedString vs = (VirtuosoExtendedString) s;
+ if (vs.iriType == VirtuosoExtendedString.IRI
+ && (vs.strType & 0x01) == 0x01) {
+ // Subject is IRI
+ return new UriRef(vs.str);
+ } else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+ return VirtuosoMGraph.this.toBNode(vs.str);
+ } else {
+ // !Cannot happen
+ throw new IllegalStateException(
+ "Subject must be an IRI or a BNODE");
+ }
+ } else {
+ throw new IllegalStateException(
+ "Subject must be an instance of VirtuosoExtendedString");
+ }
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ logger.debug("TripleBuilder.getPredicate() : {}", p);
+ if (p instanceof VirtuosoExtendedString) {
+ VirtuosoExtendedString vs = (VirtuosoExtendedString) p;
+ if (vs.iriType == VirtuosoExtendedString.IRI
+ && (vs.strType & 0x01) == 0x01) {
+ // Subject is IRI
+ return new UriRef(vs.str);
+ } else {
+ // !Cannot happen
+ throw new IllegalStateException(
+ "Predicate must be an IRI ");
+ }
+ } else {
+ throw new IllegalStateException(
+ "Predicate must be an IRI");
+ }
+ }
+
+ @Override
+ public Resource getObject() {
+ logger.debug("TripleBuilder.getObject() : {}", o);
+ if (o instanceof VirtuosoExtendedString) {
+ // In case is IRI
+ VirtuosoExtendedString vs = (VirtuosoExtendedString) o;
+ if (vs.iriType == VirtuosoExtendedString.IRI
+ && (vs.strType & 0x01) == 0x01) {
+ // Is IRI
+ return new UriRef(vs.str);
+ } else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+ //
+ return VirtuosoMGraph.this.toBNode(vs.str);
+ } else {
+ // Is a plain literal
+ return new PlainLiteralImpl(vs.str);
+ }
+ } else if (o instanceof VirtuosoRdfBox) {
+ // In case is typed literal
+ VirtuosoRdfBox rb = (VirtuosoRdfBox) o;
+ String value = (String) rb.rb_box;
+ String lang = rb.getLang();
+ String type = rb.getType();
+ if (type == null) {
+ Language language = lang == null ? null
+ : new Language(lang);
+ return new PlainLiteralImpl(value, language);
+ } else {
+ return new TypedLiteralImpl(value, new UriRef(type));
+ }
+ } else if (o == null) {
+ // Raise an exception
+ throw new IllegalStateException(
+ "Object cannot be NULL!");
+ } else {
+ // FIXME (not clear this...)
+ return new PlainLiteralImpl(o.toString());
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * Must be a VirtuosoMGraph with the same name. Subclasses are not assumed
+ * to be equals (VirtuosoGraph is not the same as VirtuosoMGraph)
+ */
+ public boolean equals(Object o) {
+ logger.debug("equals({})", o.getClass());
+ // It must be an instance of VirtuosoMGraph
+ if (o.getClass().equals(VirtuosoMGraph.class)) {
+ logger.debug("{} is a VirtuosoMGraph)", o);
+ if (((VirtuosoMGraph) o).getName().equals(this.getName())) {
+ logger.debug("Names are equal! They are equal!");
+ return true;
+ }
+ } else {
+ logger.debug("Not a VirtuosoMGraph instance: {}", o.getClass());
+ }
+ return false;
+ }
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,629 @@
+package rdf.virtuoso.storage.access;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.TripleCollection;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.EntityAlreadyExistsException;
+import org.apache.clerezza.rdf.core.access.EntityUndeletableException;
+import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
+import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import rdf.virtuoso.storage.VirtuosoMGraph;
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+import virtuoso.jdbc4.VirtuosoResultSet;
+import virtuoso.jdbc4.VirtuosoStatement;
+
+/**
+ * A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} for Virtuoso.
+ *
+ * @scr.component metatype="true" immediate="true"
+ * @scr.services interface="org.apache.clerezza.rdf.core.access.WeightedTcProvider"
+ * @scr.property name="weight" type="Integer" value="110"
+ * @scr.property name="host" type="String" value="localhost"
+ * @scr.property name="port" type="Integer" value="1111"
+ * @scr.property name="user" type="String" value="dba"
+ * @scr.property name="password" type="String" value="dba"
+ *
+ * @author enridaga
+ *
+ */
+@Component(metatype=true, immediate=true)
+@Service(WeightedTcProvider.class)
+public class VirtuosoWeightedProvider implements WeightedTcProvider {
+ @Property(value="localhost", description="The host running the Virtuoso server")
+ public static final String HOST = "host";
+ @Property(intValue=1111, description="The port number")
+ public static final String PORT= "port";
+ @Property(value="dba", description="User name")
+ public static final String USER = "user";
+ @Property(value="dba", description="User password")
+ public static final String PASSWORD = "password";
+
+ /**
+ * Virtuoso JDBC Driver class
+ */
+ public static final String DRIVER = "virtuoso.jdbc4.Driver";
+
+ public static final int DEFAULT_WEIGHT = 110;
+
+ @Property(intValue=DEFAULT_WEIGHT, description="Weight assigned to this provider")
+ public static final String WEIGHT = "weight";
+
+ /**
+ * MAP OF LOADED GRAPHS
+ */
+ private Map<UriRef, VirtuosoMGraph> graphs = null;
+
+ /**
+ * JDBC Connection to Virtuoso DBMS
+ */
+ private VirtuosoConnection connection = null;
+
+ /**
+ * Weight
+ */
+ private int weight = DEFAULT_WEIGHT;
+
+ /**
+ * Logger
+ */
+ private Logger logger = LoggerFactory
+ .getLogger(VirtuosoWeightedProvider.class);
+
+ /**
+ * Creates a new {@link VirtuosoWeightedProvider}.
+ *
+ * Before the weighted provider can be used, the method
+ * <code>activate</code> has to be called.
+ */
+ public VirtuosoWeightedProvider() {
+ logger.debug("Created VirtuosoWeightedProvider.");
+ }
+
+ /**
+ * Creates a new {@link VirtuosoWeightedProvider}
+ *
+ * @param connection
+ */
+ public VirtuosoWeightedProvider(VirtuosoConnection connection) {
+ logger.debug("Created VirtuosoWeightedProvider with connection: {}",
+ connection);
+ this.connection = connection;
+ }
+
+ /**
+ * Creates a new {@link VirtuosoWeightedProvider}
+ *
+ * @param connection
+ * @param weight
+ */
+ public VirtuosoWeightedProvider(VirtuosoConnection connection, int weight) {
+ logger.debug(
+ "Created VirtuosoWeightedProvider with connection = {} and weight = {}.",
+ connection, weight);
+ this.weight = weight;
+ this.connection = connection;
+ }
+
+ /**
+ * Activates this component.<br />
+ *
+ * @param cCtx
+ * Execution context of this component. A value of null is
+ * acceptable when you set the property connection
+ * @throws ConfigurationException
+ * @throws IllegalArgumentException
+ * No component context given and connection was not set.
+ */
+ @Activate
+ public void activate(ComponentContext cCtx) {
+ logger.info("activate(ComponentContext {})", cCtx);
+ logger.info("Activating VirtuosoWeightedProvider...");
+ if (cCtx == null && connection == null) {
+ logger.error("No component context given and connection was not set");
+ throw new IllegalArgumentException(
+ "No component context given and connection was not set");
+ } else if (cCtx != null) {
+ logger.debug("Context is given: {}", cCtx);
+ String pid = (String) cCtx.getProperties().get(
+ Constants.SERVICE_PID);
+ try {
+ // FIXME The following should not be needed...
+ try {
+ this.weight = (Integer) cCtx.getProperties().get(WEIGHT);
+ } catch (NumberFormatException nfe) {
+ logger.warn(nfe.toString());
+ logger.warn("Setting weight to defaults");
+ this.weight = DEFAULT_WEIGHT;
+ }
+
+ /**
+ * Retrieve connection properties
+ */
+ String host = (String) cCtx.getProperties().get(HOST);
+ int port = (Integer) cCtx.getProperties().get(PORT);
+ String user = (String) cCtx.getProperties().get(USER);
+ String pwd = (String) cCtx.getProperties().get(PASSWORD);
+
+ // Build connection string
+ String connStr = new StringBuilder().append("jdbc:virtuoso://")
+ .append(host).append(":").append(port).toString();
+ // Init connection
+ this.initConnection(connStr, user, pwd);
+
+ // Debug activation
+ if (logger.isDebugEnabled()) {
+ logger.debug("Component context properties: ");
+ logger.debug("> host: {}", host);
+ logger.debug("> port: {}", port);
+ logger.debug("> user: {}", user);
+ // We hide the password in log files:
+ MessageDigest algorithm;
+ try {
+ algorithm = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ algorithm.reset();
+ algorithm.update(pwd.getBytes());
+ byte messageDigest[] = algorithm.digest();
+
+ StringBuffer hexString = new StringBuffer();
+ for (int i = 0; i < messageDigest.length; i++) {
+ hexString.append(Integer
+ .toHexString(0xFF & messageDigest[i]));
+ }
+ String foo = messageDigest.toString();
+ logger.debug("> password: {}", foo);
+ }
+ logger.info("Connection to {} initialized. User is {}",
+ connStr, user);
+ } catch (VirtuosoException e) {
+ logger.error(
+ "A problem occurred while intializing connection to Virtuoso",
+ e);
+ logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+ cCtx.disableComponent(pid);
+ throw new ComponentException(e.getLocalizedMessage());
+ } catch (SQLException e) {
+ logger.error(
+ "A problem occurred while intializing connection to Virtuoso",
+ e);
+ logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+ cCtx.disableComponent(pid);
+ throw new ComponentException(e.getLocalizedMessage());
+ } catch (ClassNotFoundException e) {
+ logger.error(
+ "A problem occurred while intializing connection to Virtuoso",
+ e);
+ logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+ cCtx.disableComponent(pid);
+ throw new ComponentException(e.getLocalizedMessage());
+ }
+ }
+ logger.info("Activated VirtuosoWeightedProvider.");
+ }
+
+ /**
+ * Deactivates this component.
+ *
+ * @param cCtx
+ * component context provided by OSGi
+ */
+ @Deactivate
+ public void deactivate(ComponentContext cCtx) {
+ logger.debug("deactivate(ComponentContext {})", cCtx);
+ try {
+ if (this.connection != null) {
+ if (this.connection.isClosed()) {
+ logger.debug("Connection is already closed");
+ } else {
+ logger.debug("Closing connection");
+ // We close the connection
+ this.connection.close();
+ }
+ }
+ } catch (Exception re) {
+ logger.warn(re.toString(), re);
+ throw new RuntimeException(re);
+ }
+ logger.info("Shutdown complete.");
+ }
+
+ /**
+ * Initialize the JDBC connection
+ *
+ * @param connStr
+ * @param user
+ * @param pwd
+ * @throws SQLException
+ * @throws ClassNotFoundException
+ */
+ private void initConnection(String connStr, String user, String pwd)
+ throws SQLException, ClassNotFoundException {
+ logger.debug("initConnection(String {}, String {}, String *******)",
+ connStr, user);
+ if (this.connection != null) {
+ logger.debug("Connection already instantiated: {}", this.connection);
+ logger.debug("Closing connection");
+ this.connection.close();
+ }
+ /**
+ * FIXME For some reasons, it looks the DriverManager is instantiating a
+ * new virtuoso.jdbc4.Driver instance upon any activation. (Enable debug
+ * to see this in the stderr stream)
+ */
+ logger.debug("Loading JDBC Driver");
+ Class.forName(VirtuosoWeightedProvider.DRIVER, true, this.getClass()
+ .getClassLoader());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Activating logging for DriverManager in stderr");
+ // FIXME! How to redirect logging to our logger???
+ DriverManager.setLogWriter(new PrintWriter(System.err));
+ }
+ connection = (VirtuosoConnection) DriverManager.getConnection(connStr,
+ user, pwd);
+ logger.debug("Connection initialized: {}", connection);
+ }
+
+ /**
+ * Whether the connection is active or not
+ *
+ * @return
+ */
+ public boolean isConnectionAlive() {
+ logger.debug("isConnectionAlive() : {}", connection);
+ if (this.connection == null) {
+ logger.warn("Connection is null");
+ return false;
+ }
+ if (this.connection.isClosed()) {
+ logger.warn("Connection is closed");
+ return false;
+ }
+ if (this.connection.isConnectionLost()) {
+ logger.warn("Connection is lost");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Retrieves the Graph (unmodifiable) with the given UriRef If no graph
+ * exists with such name, throws a NoSuchEntityException
+ */
+ @Override
+ public Graph getGraph(UriRef name) throws NoSuchEntityException {
+ logger.debug("getGraph(UriRef {}) ", name);
+ // If it is read-only, returns the Graph
+ // If it is not read-only, returns the getGraph() version of the MGraph
+ VirtuosoMGraph g = loadGraphOnce(name);
+ if (g instanceof Graph) {
+ return (Graph) g;
+ } else {
+ return g.getGraph();
+ }
+ }
+
+ /**
+ * Retrieves the MGraph (modifiable) with the given UriRef. If no graph
+ * exists with such name, throws a NoSuchEntityException.
+ *
+ * @return mgraph
+ */
+ @Override
+ public MGraph getMGraph(UriRef name) throws NoSuchEntityException {
+ logger.debug("getMGraph(UriRef {}) ", name);
+ VirtuosoMGraph g = loadGraphOnce(name);
+ if (g instanceof Graph) {
+ // We have this graph but only in read-only mode!
+ throw new NoSuchEntityException(name);
+ }
+ return g;
+ }
+
+ /**
+ * Load the graph once. It check whether a graph object have been alrady
+ * created for that UriRef, if yes returns it.
+ *
+ * If not check if at least 1 triple is present in the quad for such graph
+ * identifier. If yes, creates a new graph object and loads it in the map,
+ * referring to it on next calls.
+ *
+ * If no triples exists, the graph does not exists or it is not readable.
+ *
+ * WARNING! THIS SHOULD BE THE ONLY METHOD TO ACCESS THE MAP graphs
+ *
+ * @param name
+ * @return
+ */
+ private VirtuosoMGraph loadGraphOnce(UriRef name) {
+ logger.debug("loadGraphOnce({})", name);
+ // Is it the first itme we invoke a graph here?
+ if (graphs == null) {
+ graphs = new HashMap<UriRef, VirtuosoMGraph>();
+ }
+ // Check whether the graph have been already loaded once
+ if (graphs.containsKey(name)) {
+ logger.debug("{} is already loaded", name);
+ return graphs.get(name);
+ }
+
+ logger.debug("Attempt to load {}", name);
+ // Let's create the graph object
+ String SQL = "SPARQL SELECT ?G WHERE { GRAPH ?G {?A ?B ?C} . FILTER(?G = "
+ + name + ")} LIMIT 1";
+
+ Statement st;
+ try {
+ st = connection.createStatement();
+ logger.debug("Executing SQL: {}", SQL);
+ st.execute(SQL);
+ VirtuosoResultSet rs = (VirtuosoResultSet) st.getResultSet();
+ if (rs.next() == false) {
+ // The graph is empty, it is not readable or does not exists
+ logger.warn("Graph does not exists: {}", name);
+ throw new NoSuchEntityException(name);
+ } else {
+ // The graph exists and it is readable ...
+ logger.debug("Graph {} is readable", name);
+ // is it writable?
+ logger.debug("Is {} writable?", name);
+ if (canModify(name)) {
+ logger.debug("Creating writable MGraph for graph {}", name);
+ graphs.put(name, new VirtuosoMGraph(
+ name.getUnicodeString(), connection));
+ } else {
+ logger.debug("Creating read-only Graph for graph {}", name);
+ graphs.put(name, new VirtuosoMGraph(
+ name.getUnicodeString(), connection)
+ .asVirtuosoGraph());
+ }
+ return graphs.get(name);
+ }
+ } catch (VirtuosoException e) {
+ logger.error("Error while executing query/connection.", e);
+ throw new RuntimeException(e);
+ } catch (SQLException e) {
+ logger.error("Error while executing query/connection.", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Generic implementation of the get(M)Graph method. If the named graph is
+ * modifiable, behaves the same as getMGraph(UriRef name), elsewhere,
+ * behaves as getGraph(UriRef name)
+ */
+ @Override
+ public TripleCollection getTriples(UriRef name)
+ throws NoSuchEntityException {
+ logger.debug("getTriples(UriRef {}) ", name);
+ return loadGraphOnce(name);
+ }
+
+ /**
+ * Returns the list of graphs in the virtuoso quad store. The returned set
+ * is unmodifiable.
+ *
+ * @return graphs
+ */
+ @Override
+ public Set<UriRef> listGraphs() {
+ logger.debug("listGraphs()");
+ Set<UriRef> graphs = new HashSet<UriRef>();
+ // Returns the list of graphs in the virtuoso quad store
+ String SQL = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {?S ?P ?O} }";
+ try {
+ VirtuosoStatement st = (VirtuosoStatement) this.connection
+ .createStatement();
+ logger.debug("Executing SQL: {}", SQL);
+ VirtuosoResultSet rs = (VirtuosoResultSet) st.executeQuery(SQL);
+ while (rs.next()) {
+ UriRef graph = new UriRef(rs.getString(1));
+ logger.debug(" > Graph {}", graph);
+ graphs.add(graph);
+ }
+ } catch (VirtuosoException e) {
+ logger.error("Error while executing query/connection.", e);
+ throw new RuntimeException(e);
+ }
+ return Collections.unmodifiableSet(graphs);
+ }
+
+ @Override
+ public Set<UriRef> listMGraphs() {
+ logger.debug("listMGraphs()");
+ Set<UriRef> graphs = listGraphs();
+ Set<UriRef> mgraphs = new HashSet<UriRef>();
+ logger.debug("Modifiable graphs:");
+ for (UriRef u : graphs) {
+ if (canModify(u)) {
+ logger.debug(" > {}", u);
+ mgraphs.add(u);
+ }
+ }
+ return Collections.unmodifiableSet(mgraphs);
+ }
+
+ private long getPermissions(String graph) {
+ try {
+ logger.debug("getPermissions(String {})", graph);
+ ResultSet rs;
+ String sql = "SELECT DB.DBA.RDF_GRAPH_USER_PERMS_GET ('" + graph
+ + "','" + connection.getMetaData().getUserName() + "') ";
+ logger.debug("Executing SQL: {}", sql);
+ Statement st = connection.createStatement();
+ st.execute(sql);
+ rs = st.getResultSet();
+ rs.next();
+ long result = rs.getLong(1);
+ logger.debug("Permission: {}", result);
+ return result;
+ } catch (VirtuosoException e) {
+ logger.error("A virtuoso SQL exception occurred.");
+ throw new RuntimeException(e);
+ } catch (SQLException e) {
+ logger.error("An SQL exception occurred.");
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean canRead(UriRef graph) {
+ logger.debug("canRead(UriRef {})", graph);
+ return (isRead(getPermissions(graph.getUnicodeString())));
+ }
+
+ public boolean canModify(UriRef graph) {
+ logger.debug("canModify(UriRef {})", graph);
+ return (isWrite(getPermissions(graph.getUnicodeString())));
+ }
+
+ private boolean testPermission(long value, int bit) {
+ logger.debug("testPermission(long {},int {})", value, bit);
+ return BigInteger.valueOf(value).testBit(bit);
+ }
+
+ private boolean isRead(long permission) {
+ logger.debug("isRead(long {})", permission);
+ return testPermission(permission, 1);
+ }
+
+ private boolean isWrite(long permission) {
+ logger.debug("isWrite(long {})", permission);
+ return testPermission(permission, 2);
+ }
+
+ @Override
+ public Set<UriRef> listTripleCollections() {
+ logger.debug("listTripleCollections()");
+ // I think this should behave the same as listGraphs() in our case.
+ return listGraphs();
+ }
+
+ private VirtuosoMGraph createVirtuosoMGraph(UriRef name)
+ throws UnsupportedOperationException, EntityAlreadyExistsException {
+ logger.debug("createVirtuosoMGraph(UriRef {})", name);
+ // If the graph already exists, we throw an exception
+ try {
+ loadGraphOnce(name);
+ throw new EntityAlreadyExistsException(name);
+ } catch (NoSuchEntityException nsee) {
+ if (canModify(name)) {
+ graphs.put(name, new VirtuosoMGraph(name.getUnicodeString(),
+ connection));
+ return graphs.get(name);
+ } else {
+ logger.error("Cannot create MGraph {}", name);
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+
+ /**
+ * Creates an initially empty MGraph. If the name already exists in the
+ * store, throws an {@see EntityAlreadyExistsException}
+ */
+ @Override
+ public MGraph createMGraph(UriRef name)
+ throws UnsupportedOperationException, EntityAlreadyExistsException {
+ logger.debug("createMGraph(UriRef {})", name);
+ return createVirtuosoMGraph(name);
+ }
+
+ /**
+ * Creates a new graph with the given triples, then returns the readable
+ * (not modifiable) version of the graph
+ *
+ */
+ @Override
+ public Graph createGraph(UriRef name, TripleCollection triples)
+ throws UnsupportedOperationException, EntityAlreadyExistsException {
+ logger.debug("createGraph(UriRef {}, TripleCollection {})", name,
+ triples);
+ VirtuosoMGraph mgraph = createVirtuosoMGraph(name);
+ mgraph.addAll(triples);
+ return mgraph.getGraph();
+ }
+
+ /**
+ * Clears the given graph and removes it from the loaded graphs.
+ *
+ */
+ @Override
+ public void deleteTripleCollection(UriRef name)
+ throws UnsupportedOperationException, NoSuchEntityException,
+ EntityUndeletableException {
+ logger.debug("deleteTripleCollection(UriRef {})", name);
+ TripleCollection g = (VirtuosoMGraph) getTriples(name);
+ if (g instanceof Graph) {
+ throw new EntityUndeletableException(name);
+ } else {
+ ((MGraph) g).clear();
+ graphs.remove(name);
+ }
+ }
+
+ /**
+ * Returns the names of a graph. Personally don't know why a graph should
+ * have more then 1 identifier. Anyway, this does not happen with Virtuoso
+ *
+ * @return names
+ */
+ @Override
+ public Set<UriRef> getNames(Graph graph) {
+ logger.debug("getNames(Graph {})", graph);
+ return Collections.singleton(new UriRef(((VirtuosoMGraph) graph)
+ .getName()));
+ }
+
+ /**
+ * Returns the weight of this provider.
+ *
+ */
+ @Override
+ public int getWeight() {
+ logger.debug("getWeight()");
+ /**
+ * The weight
+ */
+ return this.weight;
+ }
+
+ /**
+ * Sets the weight
+ *
+ * @param weight
+ */
+ public void setWeight(int weight) {
+ logger.debug("setWeight(int {})",weight);
+ this.weight = weight;
+ }
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider Tue Sep 10 10:38:51 2013
@@ -0,0 +1 @@
+rdf.virtuoso.storage.access.VirtuosoWeightedProvider
\ No newline at end of file
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties Tue Sep 10 10:38:51 2013
@@ -0,0 +1,5 @@
+#log4j.rootLogger=DEBUG, S
+#log4j.appender.S = org.apache.log4j.ConsoleAppender
+#log4j.appender.S.layout = org.apache.log4j.PatternLayout
+#log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
+
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,139 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+
+/**
+ * Tests the connection to the Virtuoso DBMS
+ *
+ * @author enridaga
+ */
+public class ConnectionTest {
+
+ static final Logger log = LoggerFactory.getLogger(ConnectionTest.class);
+
+ private static VirtuosoConnection connection = null;
+
+ @BeforeClass
+ public static void before() throws ClassNotFoundException, SQLException {
+ connection = TestUtils.getConnection();
+ }
+
+ @Test
+ public void testIsClosed() {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ assertFalse(connection.isClosed());
+ }
+
+ @Test
+ public void testIsConnectionLost() {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ assertFalse(connection.isConnectionLost());
+ }
+
+ @Test
+ public void testIsReadOnly() throws VirtuosoException {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ assertFalse(connection.isReadOnly());
+ }
+
+ @Test
+ public void testConnection() {
+ log.info("testConnection()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ try {
+
+ Statement st = connection.createStatement();
+ log.debug("Populate graph <mytest>");
+ String[] queries = {
+ "sparql clear graph <mytest>",
+ "sparql insert into graph <mytest> { <xxx> <P01> \"test1\"@en }",
+ "sparql insert into graph <mytest> { <xxx> <P01> \"test2\"@it }",
+ "sparql PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> insert into graph <mytest> { <xxx> <P01> \"test3\"^^xsd:string }",
+ "sparql insert into graph <mytest> { <xxx> <P01> \"test4\" }",
+ "sparql insert into graph <mytest> { <xxx> <P01> \"test5\" . <xxx> <P02> _:b1"
+ + " . _:b1 <P03> <yyy> " + " . _:b3 <P05> <zzz> "
+ + " . _:b3 <P05> <ppp> " +
+ // This is to consider that we can force it
+ " . <nodeID://b10005> <P05> <ooo> " + " }",
+ "sparql insert into graph <mytest> { <nodeID://b10005> <property> <nodeID://b10007>}",
+ "sparql insert into graph <mytest> { <enridaga> <property> \"Literal value\"^^<http://datatype#type>}",
+ "sparql insert into graph <mytest> { <nodeID://b10005> <property> <nodeID://b10007>}" };
+ for (String q : queries) {
+ log.debug("Querying: {}", q);
+ st.execute(q);
+ }
+
+ String query = "sparql SELECT * from <mytest> WHERE {?s ?p ?o}";
+ log.debug("Querying: {}", query);
+ ResultSet rs = st.executeQuery(query);
+ TestUtils.stamp(rs);
+ } catch (SQLException e) {
+ log.error("SQL ERROR: ", e);
+ assertTrue(false);
+ } catch (Exception e) {
+ log.error("SQL ERROR: ", e);
+ assertTrue(false);
+ }
+ }
+
+ @Test
+ public void test() throws ClassNotFoundException, SQLException {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ DatabaseMetaData dm = connection.getMetaData();
+ log.debug("Username is {}", dm.getUserName());
+ Properties p = connection.getClientInfo();
+ if (p == null) {
+ log.warn("Client info is null...");
+ } else
+ for (Entry<Object, Object> e : p.entrySet()) {
+ log.info("Client info property: {} => {}", e.getKey(),
+ e.getValue());
+ }
+ String SQL = "SELECT DISTINCT id_to_iri(G) FROM DB.DBA.RDF_QUAD quad ";
+ VirtuosoConnection cn = TestUtils.getConnection();
+ long startAt = System.currentTimeMillis();
+ // get the list of quad using SQL
+ log.debug("Executing SQL: {}", SQL);
+ cn.createStatement().executeQuery(SQL);
+ long endAt = System.currentTimeMillis();
+ log.debug("Using SQL: {}ms", endAt - startAt);
+ SQL = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {?S ?P ?O} }";
+ startAt = System.currentTimeMillis();
+ // get the list of quad using SQL+SPARQL
+ log.debug("Executing SQL: {}", SQL);
+ cn.createStatement().executeQuery(SQL);
+ endAt = System.currentTimeMillis();
+ log.debug("Using SQL+SPARQL: {}ms", endAt - startAt);
+ }
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,165 @@
+package rdf.virtuoso.storage;
+
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+import org.apache.clerezza.rdf.core.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import rdf.virtuoso.storage.access.VirtuosoWeightedProvider;
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoExtendedString;
+import virtuoso.jdbc4.VirtuosoRdfBox;
+import virtuoso.jdbc4.VirtuosoResultSet;
+
+/**
+ * Utilities for tests
+ *
+ * @author enridaga
+ *
+ */
+public class TestUtils {
+
+ public static final String FOAF_NS = "http://xmlns.com/foaf/0.1/";
+
+ private static VirtuosoConnection connection = null;
+ private static String jdbcConnectionString = null;
+ private static String jdbcUser = null;
+ private static String jdbcPassword = null;
+ private static String jdbcDriver = null;
+
+ static Logger log = LoggerFactory.getLogger(TestUtils.class);
+ public static boolean SKIP = false;
+ static {
+ String skipProperty = System.getProperty("virtuoso.test");
+ if (skipProperty == null) {
+ log.warn("virtuoso.skip property is not set. We skip tests by default.");
+ SKIP = true;
+ } else
+ SKIP = !skipProperty.equals("true");
+ }
+
+ public static VirtuosoConnection getConnection()
+ throws ClassNotFoundException, SQLException {
+ if (connection == null) {
+ initConnection();
+ }
+ return connection;
+ }
+
+ private static void initConnection() throws ClassNotFoundException,
+ SQLException {
+ if (SKIP) {
+ log.warn("SKIPPING ALL TESTS!");
+ return;
+ }
+ String host = System.getProperty("virtuoso.host");
+ String port = System.getProperty("virtuoso.port");
+ jdbcUser = System.getProperty("virtuoso.user");
+ jdbcPassword = System.getProperty("virtuoso.password");
+ jdbcDriver = System.getProperty("virtuoso.driver");
+ if (host == null) {
+ host = "localhost";
+ log.info("Missing param 'host', setting to default: {}", host);
+ }
+ if (port == null) {
+ port = "1111";
+ log.info("Missing param 'port', setting to default: {}", port);
+ }
+ if (jdbcUser == null) {
+ jdbcUser = "dba";
+ log.info("Missing param 'user', setting to default: {}", jdbcUser);
+ }
+ if (jdbcPassword == null) {
+ jdbcPassword = "dba";
+ log.info("Missing param 'password', setting to default: {}",
+ jdbcPassword);
+ }
+ if (jdbcDriver == null) {
+ jdbcDriver = "virtuoso.jdbc4.Driver";
+ log.info("Missing param 'password', setting to default: {}",
+ jdbcDriver);
+ }
+
+ StringBuilder cb = new StringBuilder();
+ cb.append("jdbc:virtuoso://");
+ cb.append(host);
+ cb.append(":");
+ cb.append(port);
+ jdbcConnectionString = cb.toString();
+ Class.forName(VirtuosoWeightedProvider.DRIVER);
+ log.info("Create connection");
+ connection = (VirtuosoConnection) DriverManager.getConnection(
+ jdbcConnectionString, jdbcUser, jdbcPassword);
+
+ log.debug("Connection URL: {}", jdbcConnectionString);
+ log.debug("Connection user: {}", jdbcUser);
+ }
+
+ public static void stamp(ResultSet rs) {
+ try {
+ ResultSetMetaData rsmd;
+
+ StringBuilder output = new StringBuilder();
+ output.append(System.getProperty("line.separator"));
+ output.append("------------------------------");
+ output.append(System.getProperty("line.separator"));
+ rsmd = rs.getMetaData();
+
+ while (rs.next()) {
+ for (int i = 1; i <= rsmd.getColumnCount(); i++) {
+ String s = rs.getString(i);
+ Object o = ((VirtuosoResultSet) rs).getObject(i);
+ if (o instanceof VirtuosoExtendedString) {
+ // In case is IRI
+ VirtuosoExtendedString vs = (VirtuosoExtendedString) o;
+ if (vs.iriType == VirtuosoExtendedString.IRI
+ && (vs.strType & 0x01) == 0x01) {
+ output.append(" <" + vs.str + "> ");
+ log.debug(" {} is IRI", vs.str);
+ } else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+ log.debug(" {} is BNODE", vs.str);
+ output.append(" <" + vs.str + "> ");
+ } else {
+ // In case is untyped literal
+ log.debug(" {} is an untyped literal", vs.str);
+ output.append(vs.str);
+ }
+ } else if (o instanceof VirtuosoRdfBox) {
+ // In case is typed literal
+ VirtuosoRdfBox rb = (VirtuosoRdfBox) o;
+ output.append(rb.rb_box + " lang=" + rb.getLang()
+ + " type=" + rb.getType());
+ log.debug(" {} is an typed literal", rb.rb_box);
+
+ } else if (rs.wasNull()) {
+ log.debug(" NULL ");
+ output.append("NULL");
+ } else {
+ // Is simple untyped string
+ output.append(s);
+ }
+
+ }
+ output.append("\n");
+ }
+
+ output.append(System.getProperty("line.separator"));
+ output.append("------------------------------");
+ output.append(System.getProperty("line.separator"));
+ log.info(output.toString());
+ } catch (Exception e) {
+ log.error("ERROR", e);
+ }
+ }
+
+ public static void stamp(Triple next) {
+ log.info("> TRIPLE : "+next.getSubject().toString() + " "
+ + next.getPredicate().toString() + " "
+ + next.getObject().toString());
+ }
+
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,332 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * Credit: This code is largely cloned by the thread safe test in
+ * {@see org.apache.clerezza.rdf.sesame.storage.ThreadSafetyTest}
+ *
+ * @author enridaga
+ *
+ */
+public class ThreadSafetyTest {
+
+ private ExecutorService executor;
+ private VirtuosoMGraph mgraph;
+
+ static Logger log = LoggerFactory.getLogger(ThreadSafetyTest.class);
+
+ @Before
+ public void setUp() throws Exception {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ mgraph = new VirtuosoMGraph("ThreadSafetyTest",
+ TestUtils.getConnection());
+ executor = Executors.newCachedThreadPool();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ try {
+ executor.shutdown();
+ if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+ fail("Timeout while waiting for termination");
+ }
+ } finally {
+ mgraph.clear();
+ mgraph = null;
+ }
+ }
+
+ @Test
+ public void testProduceFirstAndThenConsume() throws Exception {
+ log.info("testProduceFirstAndThenConsume()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // Produce first...
+ Future<Result> fp = executor.submit(new Producer("A", 100));
+ fp.get().assertResult();
+
+ // ...and then consume
+ Future<Result> fc = executor.submit(new Consumer("A", 100));
+ fc.get().assertResult();
+ Iterator<Triple> it = mgraph.iterator();
+ while (it.hasNext()) {
+ TestUtils.stamp(it.next());
+ }
+ // test graph size
+ assertEquals(0, mgraph.size());
+ }
+
+ @Test
+ public void testProduceAndConsumeSingle() throws Exception {
+ log.info("testProduceAndConsumeSingle()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ List<Task> tasks = Arrays.asList(
+ new Consumer("A", 100), new Producer("A", 100));
+ List<Future<Result>> futures = executor.invokeAll(tasks);
+ for (Future<Result> future : futures) {
+ future.get().assertResult();
+ }
+ assertEquals(0, mgraph.size());
+ }
+
+ @Test
+ public void testProduceAndConsumeMultiple() throws Exception {
+ log.info("testProduceAndConsumeMultiple()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ List<Task> tasks = Arrays.asList(
+ new Consumer("A", 100), new Producer("A", 100),
+ new Consumer("B", 100), new Producer("B", 100),
+ new Consumer("C", 100), new Producer("C", 100),
+ new Consumer("D", 100), new Producer("D", 100));
+ List<Future<Result>> futures = executor.invokeAll(tasks);
+ for (Future<Result> future : futures) {
+ future.get().assertResult();
+ }
+ assertEquals(0, mgraph.size());
+ }
+
+ @Test
+ public void testProduceAndConsumeMixed() throws Exception {
+ log.info("testProduceAndConsumeMixed()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ List<? extends Task> tasks = Arrays.asList(
+ new Consumer("A", 110), new Consumer("A", 170),
+ new Consumer("B", 100), new Consumer("B", 500),
+ new Consumer("C", 230), new Consumer("C", 230),
+ new Consumer("D", 540), new Consumer("D", 10),
+ new Producer("D", 50), new Producer("D", 500),
+ new Producer("C", 400), new Producer("C", 60),
+ new Producer("B", 300), new Producer("B", 300),
+ new Producer("A", 200), new Producer("A", 80));
+ List<Future<Result>> futures = executor.invokeAll(tasks);
+ for (Future<Result> future : futures) {
+ future.get().assertResult();
+ }
+ assertEquals(0, mgraph.size());
+ }
+ /**
+ * The <code>Task</code> specifies a <code>Callable</code> whoes execution
+ * results in an <code>Integer</code>.
+ */
+ private abstract class Task implements Callable<Result> {
+
+ protected final String collectionName;
+ protected final UriRef subject;
+ protected final UriRef predicate;
+ protected final int numElements;
+
+ /**
+ * Creates a new <code>Task</code>.
+ *
+ * @param collectionName
+ * Name of the task's collection.
+ * @param numElements
+ * The number of elements to process.
+ */
+ protected Task(String collectionName, int numElements) {
+ if (collectionName == null) {
+ throw new IllegalArgumentException("Invalid name: null");
+ } else if (collectionName.length() <= 0) {
+ throw new IllegalArgumentException("Invalid name: '"
+ + collectionName + "'");
+ } else if (numElements < 0) {
+ throw new IllegalArgumentException("Invalid numElements: "
+ + numElements);
+ }
+ this.numElements = numElements;
+ this.collectionName = collectionName;
+ subject = new UriRef("http://example.org/" + "collection/"
+ + collectionName);
+ predicate = new UriRef("http://example.org/ontology/contains");
+ }
+
+ /**
+ * Causes the currently executing thread object to temporarily pause and
+ * allow other threads to execute.
+ */
+ protected void yield() {
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * This class represents a task that produces triples that are stored in the
+ * graph.
+ */
+ private class Producer extends Task {
+
+ /**
+ * Creates a new <code>Producer</code> task.
+ *
+ * @param collectionName
+ * Name of the task's collection.
+ * @param numElements
+ * The number of elements to produce.
+ */
+ public Producer(String collectionName, int numElements) {
+ super(collectionName, numElements);
+ }
+
+ @Override
+ public Result call() throws InterruptedException {
+ int counter = 0;
+ for (int elementName = 1; counter < numElements; elementName++) {
+ yield();
+ final Triple t = createTriple(elementName);
+ if (mgraph.add(t)) {
+ counter++;
+ yield();
+ } else {
+ System.out.println("WARNING: element " + t + "NOT created");
+ }
+ }
+ return new Result(collectionName, "Produced elements", numElements,
+ counter);
+ }
+
+ /**
+ * Creates a new collection element triple.
+ *
+ * @param value
+ * Value of the collection element.
+ * @return A new triple representing the collection element.
+ */
+ protected Triple createTriple(int value) {
+ final UriRef object = new UriRef("http://example.org/"
+ + collectionName + "/" + Integer.valueOf(value)
+ + Math.random());
+ return new TripleImpl(subject, predicate, object);
+ }
+ }
+
+ /**
+ * This class represents a task that produces triples that are stored in the
+ * graph.
+ */
+ private class Consumer extends Task {
+
+ /**
+ * Creates a new <code>Consumer</code> task.
+ *
+ * @param collectionName
+ * Name of the task's collection.
+ * @param numElements
+ * The number of elements to consume.
+ */
+ public Consumer(String collectionName, int numElements) {
+ super(collectionName, numElements);
+ }
+
+ /**
+ * Performs this task.
+ *
+ * @return the number of elements successfully added to the graph.
+ */
+ @Override
+ public Result call() throws InterruptedException {
+ int counter = 0;
+ while (counter < numElements) {
+ yield();
+
+ Triple triple = null;
+ mgraph.getLock().writeLock().lock();
+ try {
+ // System.out.println("synchonized");
+ Iterator<Triple> i = mgraph
+ .filter(subject, predicate, null);
+ if (i.hasNext()) {
+ triple = i.next();
+ }
+
+ if (triple != null && mgraph.remove(triple)) {
+ counter++;
+ }
+ } finally {
+ mgraph.getLock().writeLock().unlock();
+ }
+ }
+ return new Result(collectionName, "Consumed elements", numElements,
+ counter);
+ }
+ }
+
+ /**
+ * Task result that asserts the number of processed elements.
+ */
+ private class Result {
+
+ private final int expected;
+ private final int actual;
+ private final String msg;
+ private final String cn;
+
+ /**
+ * Creates a new task result that asserts the element count.
+ *
+ * @param cn
+ * Name of the affected collection.
+ * @param msg
+ * Assertion message to print.
+ * @param expected
+ * Expected number of processed elements.
+ * @param actual
+ * Actual number of processed elements.
+ */
+ public Result(String cn, String msg, int expected, int actual) {
+ this.expected = expected;
+ this.actual = actual;
+ this.msg = msg;
+ this.cn = cn;
+ }
+
+ /**
+ * Asserts this result.
+ */
+ public void assertResult() {
+ assertEquals("[" + cn + "] " + msg, expected, actual);
+ }
+ }
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,13 @@
+package rdf.virtuoso.storage;
+
+import org.apache.clerezza.rdf.core.Graph;
+
+/**
+ * Tests the {@link VirtuosoGraph} implementation of {@link Graph}
+ *
+ * @author enridaga
+ *
+ */
+public class VirtuosoGraphTest {
+
+}
Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,361 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoException;
+
+public class VirtuosoMGraphTest {
+ static VirtuosoMGraph mgraph = null;
+ static final String TEST_GRAPH_NAME = "VirtuosoMGraphTest";
+
+ static Logger log = LoggerFactory.getLogger(VirtuosoMGraphTest.class);
+
+ /**
+ * Clean before any test
+ *
+ * @throws ClassNotFoundException
+ * @throws SQLException
+ */
+ @Before
+ public void before() throws ClassNotFoundException, SQLException {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ mgraph = new VirtuosoMGraph(TEST_GRAPH_NAME, TestUtils.getConnection());
+ mgraph.clear();
+ log.debug("Clearing graph <{}>", TEST_GRAPH_NAME);
+ }
+
+ final UriRef enridaga = new UriRef("enridaga");
+ final UriRef alexdma = new UriRef("alexdma");
+ final UriRef anuzzolese = new UriRef("anuzzolese");
+ final UriRef predicate = new UriRef("http://property/name");
+ final PlainLiteral object = new PlainLiteralImpl("Enrico Daga");
+ final UriRef knows = new UriRef(TestUtils.FOAF_NS + "knows");
+
+ @Test
+ public void testAddSingle() {
+ log.info("testAddSingle()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ Triple triple = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return predicate;
+ }
+
+ @Override
+ public Resource getObject() {
+ return object;
+ }
+ };
+
+ boolean success = mgraph.add(triple);
+ assertTrue(success);
+ assertTrue(mgraph.size() == 1);
+ }
+
+ @Test
+ public void testFilter() {
+ log.info("testFilter(); Test filter(s,p,o)");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // We use testAdd to prepare this
+ testAddSingle();
+ Iterator<Triple> it = mgraph.filter(enridaga, predicate, object);
+ boolean found = false;
+ while (it.hasNext()) {
+ found = true;
+ Triple t = it.next();
+ log.debug("Found matching triple: {}", t);
+ assertEquals(t.getSubject(), enridaga);
+ assertEquals(t.getPredicate(), predicate);
+ assertEquals(t.getObject(), object);
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testFilterSubject() {
+ log.info("testFilterSubject(); Test filter(s,null,null)");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // We use testAdd to prepare this
+ testAddSingle();
+ Iterator<Triple> it = mgraph.filter(enridaga, null, null);
+ boolean found = false;
+ while (it.hasNext()) {
+ found = true;
+ Triple t = it.next();
+ if (log.isDebugEnabled()) {
+ log.debug("Found matching triple: {}", t);
+ TestUtils.stamp(t);
+ }
+ assertEquals(t.getSubject(), enridaga);
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testFilterPredicate() {
+ log.info("testFilterPredicate(); Test filter(null,p,null)");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // We use testAdd to prepare this
+ testAddSingle();
+ Iterator<Triple> it = mgraph.filter(null, predicate, null);
+ boolean found = false;
+ while (it.hasNext()) {
+ found = true;
+ Triple t = it.next();
+ if (log.isDebugEnabled()) {
+ log.debug("Found matching triple: {}", t);
+ TestUtils.stamp(t);
+ }
+ assertEquals(t.getPredicate(), predicate);
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testFilterObject() {
+ log.info("testFilterObject(); Test filter(null,null,o)");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // We use testAdd to prepare this
+ testAddSingle();
+ Iterator<Triple> it = mgraph.filter(null, null, object);
+ boolean found = false;
+ while (it.hasNext()) {
+ found = true;
+ Triple t = it.next();
+ if (log.isDebugEnabled()) {
+ log.debug("Found matching triple: {}", t);
+ TestUtils.stamp(t);
+ }
+ assertEquals(t.getObject(), object);
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testSize() {
+ log.info("testSize()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ // We use testAdd to prepare this
+ testAddSingle();
+ // Should be 1 at this time
+ log.debug("How many triples are in graph <{}>? {}", TEST_GRAPH_NAME,
+ mgraph.size());
+ assertTrue(mgraph.size() > 0);
+ }
+
+ @Test
+ public void testIncreaseSize() {
+ log.info("testIncreaseSize()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ int beforeSize = mgraph.size();
+ Triple t = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return knows;
+ }
+
+ @Override
+ public Resource getObject() {
+ return alexdma;
+ }
+ };
+ assertTrue(mgraph.add(t));
+ int afterSize = mgraph.size();
+ assertEquals(beforeSize + 1, afterSize);
+ }
+
+ @Test
+ public void testAddRemoveSize() {
+ log.info("testAddRemoveSize()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ int beforeSize = mgraph.size();
+ Triple t = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return knows;
+ }
+
+ @Override
+ public Resource getObject() {
+ return alexdma;
+ }
+ };
+ assertTrue(mgraph.add(t));
+ assertTrue(mgraph.remove(t));
+ int afterSize = mgraph.size();
+ assertEquals(beforeSize, afterSize);
+ }
+
+ @Test
+ public void testGetGraphReadOnly() {
+ log.info("testGetGraphReadOnly()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ Graph g = mgraph.getGraph();
+ Triple t = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return knows;
+ }
+
+ @Override
+ public Resource getObject() {
+ return anuzzolese;
+ }
+ };
+ // This should not be allowed
+ boolean success;
+ try {
+ success = g.add(t);
+ } catch (UnsupportedOperationException e) {
+ success = false;
+ }
+ assertFalse(success);
+ }
+
+ @Test
+ public void testContains() {
+ log.info("testContains()");
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ Triple t = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return knows;
+ }
+
+ @Override
+ public Resource getObject() {
+ return anuzzolese;
+ }
+ };
+ boolean addWorks = mgraph.add(t);
+ assertTrue(addWorks);
+
+ // This second triple is equivalent
+ Triple t2 = new Triple() {
+
+ @Override
+ public NonLiteral getSubject() {
+ return enridaga;
+ }
+
+ @Override
+ public UriRef getPredicate() {
+ return knows;
+ }
+
+ @Override
+ public Resource getObject() {
+ return anuzzolese;
+ }
+ };
+ Iterator<Triple> it = mgraph.filter(t2.getSubject(), t2.getPredicate(),
+ t2.getObject());
+ while (it.hasNext()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Found matching triple");
+ TestUtils.stamp(it.next());
+ }else{
+ it.next();
+ }
+ }
+ assertTrue(mgraph.contains(t2));
+ // Also the related read-only graph
+ assertTrue(mgraph.getGraph().contains(t2));
+ }
+
+ @After
+ public void clear() throws VirtuosoException, ClassNotFoundException,
+ SQLException {
+ if (TestUtils.SKIP) {
+ log.warn("SKIPPED");
+ return;
+ }
+ log.debug("Clearing graph <{}> of size {}", TEST_GRAPH_NAME,
+ mgraph.size());
+ log.debug("Removing graph <{}>", TEST_GRAPH_NAME);
+ Statement st = TestUtils.getConnection().createStatement();
+ st.execute("SPARQL CLEAR GRAPH <" + TEST_GRAPH_NAME + ">");
+ }
+}