clerezza-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From enrid...@apache.org
Subject [4/5] git commit: CLEREZZA-810 Packages renamed
Date Sun, 16 Mar 2014 18:51:38 GMT
CLEREZZA-810 Packages renamed


Project: http://git-wip-us.apache.org/repos/asf/clerezza/repo
Commit: http://git-wip-us.apache.org/repos/asf/clerezza/commit/25694741
Tree: http://git-wip-us.apache.org/repos/asf/clerezza/tree/25694741
Diff: http://git-wip-us.apache.org/repos/asf/clerezza/diff/25694741

Branch: refs/heads/master
Commit: 25694741222674fdb2977d35fb008a91c2f07c59
Parents: f5f5112
Author: enridaga <enridaga@apache.org>
Authored: Sun Mar 16 18:49:16 2014 +0000
Committer: enridaga <enridaga@apache.org>
Committed: Sun Mar 16 18:49:16 2014 +0000

----------------------------------------------------------------------
 .../rdf/virtuoso/storage/VirtuosoBNode.java     |  27 +
 .../rdf/virtuoso/storage/VirtuosoGraph.java     |  94 ++
 .../rdf/virtuoso/storage/VirtuosoMGraph.java    | 191 ++++
 .../rdf/virtuoso/storage/access/DataAccess.java | 860 +++++++++++++++++
 .../access/VirtuosoWeightedProvider.java        | 923 +++++++++++++++++++
 .../rdf/virtuoso/storage/VirtuosoBNode.java     |  27 -
 .../rdf/virtuoso/storage/VirtuosoGraph.java     |  94 --
 .../rdf/virtuoso/storage/VirtuosoMGraph.java    | 191 ----
 .../rdf/virtuoso/storage/access/DataAccess.java | 860 -----------------
 .../access/VirtuosoWeightedProvider.java        | 923 -------------------
 .../src/test/java/.DS_Store                     | Bin 0 -> 6148 bytes
 .../clerezza/rdf/virtuoso/storage/.DS_Store     | Bin 0 -> 6148 bytes
 .../rdf/virtuoso/storage/ConnectionTest.java    | 138 +++
 .../rdf/virtuoso/storage/RdfIOTest.java         | 352 +++++++
 .../rdf/virtuoso/storage/TestUtils.java         | 185 ++++
 .../rdf/virtuoso/storage/ThreadSafetyTest.java  | 341 +++++++
 .../rdf/virtuoso/storage/VirtuosoGraphTest.java |  32 +
 .../virtuoso/storage/VirtuosoMGraphTest.java    | 526 +++++++++++
 .../virtuoso/storage/access/DataAccessTest.java | 111 +++
 .../access/VirtuosoWeightedProviderTest.java    | 310 +++++++
 .../rdf/virtuoso/storage/ConnectionTest.java    | 138 ---
 .../java/rdf/virtuoso/storage/RdfIOTest.java    | 350 -------
 .../java/rdf/virtuoso/storage/TestUtils.java    | 185 ----
 .../rdf/virtuoso/storage/ThreadSafetyTest.java  | 340 -------
 .../rdf/virtuoso/storage/VirtuosoGraphTest.java |  31 -
 .../virtuoso/storage/VirtuosoMGraphTest.java    | 525 -----------
 .../virtuoso/storage/access/DataAccessTest.java | 110 ---
 .../access/VirtuosoWeightedProviderTest.java    | 309 -------
 .../src/test/resources/log4j.properties         |   1 +
 29 files changed, 4091 insertions(+), 4083 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoBNode.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoBNode.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoBNode.java
new file mode 100644
index 0000000..b1ce14b
--- /dev/null
+++ b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoBNode.java
@@ -0,0 +1,27 @@
+package org.apache.clerezza.rdf.virtuoso.storage;
+
+import org.apache.clerezza.rdf.core.BNode;
+
+public class VirtuosoBNode extends BNode {
+	private String skolemId;
+	public VirtuosoBNode(String skolemId) {
+		this.skolemId = skolemId;
+	}
+	
+	public String getSkolemId(){
+		return skolemId;
+	}
+	
+	public String asSkolemIri(){
+		return new StringBuilder().append('<').append(skolemId).append('>').toString();
+	}
+	
+	public String toString(){
+		return skolemId;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		return (obj instanceof VirtuosoBNode) && (obj.toString().equals(toString()));
+	}
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoGraph.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoGraph.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoGraph.java
new file mode 100644
index 0000000..2516fdc
--- /dev/null
+++ b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoGraph.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.clerezza.rdf.virtuoso.storage;
+
+import java.util.Collection;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.virtuoso.storage.access.DataAccess;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 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, DataAccess dataAccess) {
+		super(name, dataAccess);
+	}
+
+	@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;
+	}
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoMGraph.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoMGraph.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoMGraph.java
new file mode 100644
index 0000000..e4dc6d6
--- /dev/null
+++ b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/VirtuosoMGraph.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.clerezza.rdf.virtuoso.storage;
+
+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.Graph;
+import org.apache.clerezza.rdf.core.Literal;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+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.access.LockableMGraph;
+import org.apache.clerezza.rdf.core.impl.AbstractMGraph;
+import org.apache.clerezza.rdf.virtuoso.storage.access.DataAccess;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 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();
+
+	/**
+	 * Logger
+	 */
+	protected Logger logger = LoggerFactory.getLogger(VirtuosoMGraph.class);
+
+	/**
+	 * The name of the graph
+	 */
+	private String name = null;
+	// private int size = 0;
+
+	private VirtuosoGraph readOnly = null;
+	private DataAccess dataAccess = null;
+
+	/**
+	 * Creates a {@link VirtuosoMGraph} Virtuoso MGraph binds directly to the
+	 * store.
+	 * 
+	 * @param connection
+	 */
+	public VirtuosoMGraph(String name, DataAccess dataAccess) {
+		logger.debug("VirtuosoMGraph(String {}, DataAccess {})", name,
+				dataAccess);
+		this.name = name;
+		// this.provider = provider;
+		this.dataAccess = dataAccess;
+	}
+
+	@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, getDataAccess());
+		}
+		return readOnly;
+	}
+
+	protected DataAccess getDataAccess() {
+		return this.dataAccess;
+	}
+
+	@Override
+	protected Iterator<Triple> performFilter(NonLiteral subject,
+			UriRef predicate, Resource object) {
+		readLock.lock();
+		Iterator<Triple> tit = getDataAccess().filter(getName(), subject,
+				predicate, object);
+		readLock.unlock();
+		return tit;
+	}
+
+	/**
+	 * We load the size every time it is requested.
+	 */
+	@Override
+	public int size() {
+		logger.debug("size()");
+		readLock.lock();
+		int size = getDataAccess().size(getName());
+		readLock.unlock();
+		return size;
+	}
+
+	@Override
+	public void clear() {
+		logger.debug("clear()");
+		writeLock.lock();
+		getDataAccess().clearGraph(getName());
+		writeLock.unlock();
+	}
+
+	protected boolean performAdd(Triple triple) {
+		logger.debug("performAdd(Triple {})", triple);
+
+		// If the object is a very long literal we use plan B
+		// Reason:
+		// Virtuoso Error:
+		// SR449: Key is too long, index RDF_QUAD, ruling part is 1901 bytes
+		// that exceeds 1900 byte limit
+		// We use alternative method for literals
+		writeLock.lock();
+		if (triple.getObject() instanceof Literal) {
+			getDataAccess().performAddPlanB(getName(), triple);
+		}else{
+			getDataAccess().insertQuad(getName(), triple);
+		}
+		writeLock.unlock();
+		return true;
+	}
+
+	protected boolean performRemove(Triple triple) {
+		logger.debug("performRemove(Triple triple)", triple);
+		writeLock.lock();
+		getDataAccess().deleteQuad(getName(), triple);
+		writeLock.unlock();
+		return true;
+	}
+
+	/**
+	 * Returns the graph name
+	 * 
+	 * @return
+	 */
+	public String getName() {
+		logger.debug("getName()");
+		return name;
+	}
+
+	/**
+	 * 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;
+	}
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/DataAccess.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/DataAccess.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/DataAccess.java
new file mode 100644
index 0000000..bb7a685
--- /dev/null
+++ b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/DataAccess.java
@@ -0,0 +1,860 @@
+package org.apache.clerezza.rdf.virtuoso.storage.access;
+
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.Language;
+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.impl.PlainLiteralImpl;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.core.impl.TypedLiteralImpl;
+import org.apache.clerezza.rdf.virtuoso.storage.VirtuosoBNode;
+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.VirtuosoPreparedStatement;
+import virtuoso.jdbc4.VirtuosoRdfBox;
+import virtuoso.jdbc4.VirtuosoResultSet;
+
+/**
+ * 
+ * @author enridaga
+ *
+ */
+public class DataAccess {
+	private Logger logger = LoggerFactory.getLogger(DataAccess.class);
+
+	final static String DRIVER = "virtuoso.jdbc4.Driver";
+
+	// XXX This is only used to create a new bnode identifier in virtuoso
+	final static String INSERT_NEW_BNODE = "SPARQL INSERT INTO iri(??) { [] `iri(??)` "
+			+ "`iri(??)`}";
+
+	// XXX This is only used to delete a new bnode identifier in virtuoso
+	final static String DELETE_NEW_BNODE = "SPARQL DELETE FROM iri(??) { ?s ?p ?o } WHERE { ?s ?p ?o . filter( ?p = iri(??) && "
+			+ " ?o = iri(??) ) }";
+
+	final static String INSERT_QUAD = "SPARQL INSERT INTO iri(??) {`iri(??)` `iri(??)` "
+			+ "`bif:__rdf_long_from_batch_params(??,??,??)`}";
+	final static String DELETE_QUAD = "SPARQL DELETE FROM iri(??) { ?s ?p ?o } WHERE { ?s ?p ?o . filter( ?s = iri(??) && ?p = iri(??) && "
+			+ " ?o = bif:__rdf_long_from_batch_params(??,??,??) ) } ";
+	final static String LIST_GRAPHS = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {[] [] []} }";
+	final static String CLEAR_GRAPH = "SPARQL CLEAR GRAPH iri(??)";
+	final static String COUNT_TRIPLES_OF_GRAPH = "SPARQL SELECT COUNT(*) WHERE { bind( iri(??) as ?graph ) . graph ?graph { [] [] [] } }";
+	final static String SELECT__ = "SPARQL SELECT ?subject ?predicate ?object WHERE { bind( iri(??) as ?graph ) . GRAPH ?graph { ?subject ?predicate ?object ";
+	final static String SELECT_TRIPLES_NULL_NULL_NULL = SELECT__ + " } }";
+	final static String SELECT_TRIPLES_S_NULL_NULL = SELECT__ + " . FILTER( ?subject = iri(??) ) } }";
+	final static String SELECT_TRIPLES_S_P_NULL = SELECT__ + " . FILTER( ?subject = iri(??) && ?predicate = iri(??) ) } }";
+	final static String SELECT_TRIPLES_S_P_O = SELECT__ + " . FILTER( ?subject = iri(??) && ?predicate = iri(??) && ?object = bif:__rdf_long_from_batch_params(??,??,??) ) } }";
+	final static String SELECT_TRIPLES_NULL_P_NULL = SELECT__ + " . FILTER( ?predicate = iri(??) ) } }";
+	final static String SELECT_TRIPLES_NULL_P_O = SELECT__ + " . FILTER( ?predicate = iri(??) && ?object = bif:__rdf_long_from_batch_params(??,??,??) ) } }";
+	final static String SELECT_TRIPLES_NULL_NULL_O = SELECT__ + " . FILTER( ?object = bif:__rdf_long_from_batch_params(??,??,??) ) } }";
+	final static String SELECT_TRIPLES_S_NULL_O = SELECT__ + " . FILTER( ?subject = iri(??) && ?object = bif:__rdf_long_from_batch_params(??,??,??) ) } }";
+
+	private final static String[] filterQueries = new String[] {
+			SELECT_TRIPLES_NULL_NULL_NULL, SELECT_TRIPLES_S_NULL_NULL,
+			SELECT_TRIPLES_S_P_O, SELECT_TRIPLES_NULL_NULL_O,
+			SELECT_TRIPLES_NULL_P_NULL, SELECT_TRIPLES_S_P_NULL,
+			SELECT_TRIPLES_NULL_P_O, SELECT_TRIPLES_S_NULL_O };
+
+	/**
+	 * Bidirectional map for managing the conversion from virtuoso blank nodes
+	 * (strings) to clerezza blank nodes and vice versa.
+	 */
+	private final BidiMap<VirtuosoBNode, BNode> bnodesMap;
+
+	private Map<String, VirtuosoPreparedStatement> preparedStatements = null;
+	private VirtuosoConnection connection = null;
+	private String connectionString;
+	private String user;
+	private String pwd;
+
+	// We protect the constructor from outside the package...
+	DataAccess(String connectionString, String user, String pwd) {
+		this.connectionString = connectionString;
+		this.user = user;
+		this.pwd = pwd;
+		connection = createConnection();
+		
+		// Init collections
+		this.preparedStatements = new HashMap<String,VirtuosoPreparedStatement>();
+		this.bnodesMap = new BidiMapImpl<VirtuosoBNode, BNode>();
+
+	}
+
+	private VirtuosoConnection createConnection() {
+		try {
+			Class.forName(VirtuosoWeightedProvider.DRIVER, true, this
+					.getClass().getClassLoader());
+			VirtuosoConnection c = (VirtuosoConnection) DriverManager
+					.getConnection(connectionString, user, pwd);
+			c.setAutoCommit(true);
+			return c;
+		} catch (ClassNotFoundException e) {
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	// A simple renewal policy
+	private int statementCalls = 0;
+	protected PreparedStatement getStatement(String query)
+			throws VirtuosoException {
+		if(statementCalls >= 10000){
+			statementCalls=0; 
+			renew();
+		}else{
+			statementCalls++;
+		}
+		if (!preparedStatements.containsKey(query)) {
+			VirtuosoPreparedStatement ps = (VirtuosoPreparedStatement) connection
+					.prepareStatement(query);
+			preparedStatements.put(query, ps);
+		}
+		return preparedStatements.get(query);
+	}
+
+	private VirtuosoBNode toVirtBnode(BNode bnode) {
+		logger.debug("toVirtBnode(BNode {})", bnode);
+		if (bnode instanceof VirtuosoBNode) {
+			return ((VirtuosoBNode) bnode);
+		} else {
+			VirtuosoBNode virtBnode = bnodesMap.getKey(bnode);
+			if (virtBnode == null) {
+				// We create a local bnode mapped to the BNode given
+				virtBnode = nextVirtBnode(bnode);
+				bnodesMap.put(virtBnode, bnode);
+			}
+			return virtBnode;
+		}
+	}
+
+	public void renew() {
+		logger.trace("renewing...");
+		close();
+		connection = createConnection();
+	}
+
+	public void close() {
+		logger.trace("closing resources...");
+		Collection<VirtuosoPreparedStatement> pss = preparedStatements.values();
+		for (VirtuosoPreparedStatement ps : pss) {
+			try {
+				logger.trace("Closing prepared statement {}", ps);
+				ps.close();
+			} catch (Exception e) {
+				logger.error("Cannot close statement", e);
+			}
+		}
+		logger.trace("closed {} statements.", pss.size());
+		preparedStatements.clear();
+		try {
+			connection.close();
+			logger.trace("Connection closed");
+		} catch (Exception e) {
+			logger.error("Cannot close connection", e);
+		}
+	}
+
+	private void bindValue(PreparedStatement st, int i, Resource object)
+			throws SQLException {
+		if (object instanceof UriRef) {
+			st.setInt(i, 1);
+			st.setString(i + 1, ((UriRef) object).getUnicodeString());
+			st.setNull(i + 2, java.sql.Types.VARCHAR);
+		} else if (object instanceof BNode) {
+			st.setInt(i, 1);
+			st.setString(i + 1, ((VirtuosoBNode) object).getSkolemId());
+			st.setNull(i + 2, java.sql.Types.VARCHAR);
+		} else if (object instanceof TypedLiteral) {
+			TypedLiteral tl = ((TypedLiteral) object);
+			st.setInt(i, 4);
+			st.setString(i + 1, tl.getLexicalForm());
+			st.setString(i + 2, tl.getDataType().getUnicodeString());
+		} else if (object instanceof PlainLiteral) {
+			PlainLiteral pl = (PlainLiteral) object;
+			if (pl.getLanguage() != null) {
+				st.setInt(i, 5);
+				st.setString(i + 1, pl.getLexicalForm());
+				st.setString(i + 2, pl.getLanguage().toString());
+			} else {
+				st.setInt(i, 3);
+				st.setString(i + 1, pl.getLexicalForm());
+				st.setNull(i + 2, java.sql.Types.VARCHAR);
+			}
+		} else
+			throw new IllegalArgumentException(object.toString());
+	}
+
+	private void bindPredicate(PreparedStatement st, int i, UriRef predicate)
+			throws SQLException {
+		st.setString(i, predicate.getUnicodeString());
+	}
+
+	private void bindSubject(PreparedStatement st, int i, NonLiteral subject)
+			throws SQLException {
+		if (subject instanceof UriRef) {
+			st.setString(i, ((UriRef) subject).getUnicodeString());
+		} else {
+			st.setString(i, ((VirtuosoBNode) subject).getSkolemId());
+		}
+	}
+
+	private void bindGraph(PreparedStatement st, int i, UriRef uriRef)
+			throws SQLException {
+		st.setString(i, uriRef.getUnicodeString());
+	}
+	
+
+	private void bindGraph(PreparedStatement st, int i, String uri)
+			throws SQLException {
+		st.setString(i, uri);
+	}
+
+	/**
+	 * Generate a new local bnode to be used in virtuoso queries
+	 * 
+	 * @return
+	 */
+	private VirtuosoBNode nextVirtBnode(BNode bn) {
+		logger.debug("nextVirtBnode(BNode)");
+		/**
+		 * XXX Here we force virtuoso to generate a valid skolem uri for a blank
+		 * node we are going to insert for the first time.
+		 * 
+		 * All this process should be more efficient, possibly invoking a native
+		 * procedure, instead of insert/select/delete a fake triple as it is
+		 * now.
+		 */
+		UriRef g = new UriRef("urn:x-virtuoso:bnode-tmp");
+		UriRef p = new UriRef("urn:x-virtuoso:bnode:object");
+		UriRef o = new UriRef(new StringBuilder()
+				.append("urn:x-virtuoso:bnode:").append(bn).toString());
+
+		Exception e = null;
+		VirtuosoResultSet rs = null;
+
+		String bnodeId = null;
+		// insert
+		try {
+			PreparedStatement insert = getStatement(INSERT_NEW_BNODE);
+			bindGraph(insert, 1, g);
+			bindPredicate(insert, 2, p);
+			bindSubject(insert, 3, o);
+			insert.executeUpdate();
+
+			// select
+			PreparedStatement select = getStatement(SELECT_TRIPLES_NULL_P_O);
+			bindGraph(select, 1, g);
+			bindPredicate(select, 2, p);
+			bindValue(select, 3, o);
+			rs = (VirtuosoResultSet) select.executeQuery();
+			rs.next();
+			bnodeId = rs.getString(1);
+			rs.close();
+
+			// delete
+			PreparedStatement delete = getStatement(DELETE_NEW_BNODE);
+			bindGraph(delete, 1, g);
+			bindPredicate(delete, 2, p);
+			bindSubject(delete, 3, o); // It is a IRI
+			delete.executeUpdate();
+
+		} catch (VirtuosoException ve) {
+			logger.error("ERROR while executing statement", ve);
+			e = ve;
+		} catch (SQLException se) {
+			logger.error("ERROR while executing statement", se);
+			e = se;
+		} finally {
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Exception ex) {
+				logger.error("Error attempting to close result set", ex);
+			}
+		}
+		if (e != null) {
+			throw new RuntimeException(e);
+		}
+		return new VirtuosoBNode(bnodeId);
+
+	}
+	public void insertQuad(String graph, Triple triple) {
+		NonLiteral s = triple.getSubject(); 
+		UriRef p = triple.getPredicate() ;
+		Resource o = triple.getObject();
+		
+		// Skolemize bnodes
+		if(s instanceof BNode){
+			s = toVirtBnode((BNode) s);
+		}
+		if(o instanceof BNode){
+			o = toVirtBnode((BNode) o);
+		}
+		
+		try {
+			PreparedStatement st = getStatement(INSERT_QUAD);
+			bindGraph(st, 1, graph);
+			bindSubject(st, 2, s);
+			bindPredicate(st, 3, p);
+			bindValue(st, 4, o);
+			st.executeUpdate();
+		} catch (VirtuosoException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	public void deleteQuad(String graph,  Triple triple) {
+		NonLiteral s = triple.getSubject(); 
+		UriRef p = triple.getPredicate() ;
+		Resource o = triple.getObject();
+
+		// Skolemize bnodes
+		if(s instanceof BNode){
+			s = toVirtBnode((BNode) s);
+		}
+		if(o instanceof BNode){
+			o = toVirtBnode((BNode) o);
+		}
+		try {
+			PreparedStatement st = getStatement(DELETE_QUAD);
+			bindGraph(st, 1, graph);
+			bindSubject(st, 2, s);
+			bindPredicate(st, 3, p);
+			bindValue(st, 4, o);
+			st.executeUpdate();
+		} catch (VirtuosoException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	public Set<UriRef> listGraphs() {
+		try {
+			PreparedStatement st = getStatement(LIST_GRAPHS);
+			ResultSet rs = st.executeQuery();
+			Set<UriRef> graphs = new HashSet<UriRef>();
+			while (rs.next()) {
+				UriRef graph = new UriRef(rs.getString(1));
+				logger.debug(" > Graph {}", graph);
+				graphs.add(graph);
+			}
+			return Collections.unmodifiableSet(graphs);
+		} catch (VirtuosoException e) {
+			logger.error("Cannot execute query", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("Cannot execute query", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	public void clearGraph(String graph) {
+		try {
+			PreparedStatement st = getStatement(CLEAR_GRAPH);
+			bindGraph(st, 1, graph);
+			st.executeUpdate();
+			try {
+				connection.commit();
+			} catch (Exception e) {
+				logger.error("Rolling back");
+				connection.rollback();
+			}
+		} catch (VirtuosoException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("Cannot execute statement", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	private VirtuosoBNode toBNode(String virtbnode) {
+		VirtuosoBNode bnode;
+		bnode = new VirtuosoBNode(virtbnode);
+		return bnode;
+	}
+
+	public Iterator<Triple> filter(String graph, NonLiteral subject,
+			UriRef predicate, Resource object) {
+		
+
+		// Override blank node object to be a skolemized IRI
+		if (object != null && object instanceof BNode) {
+			object = new UriRef(toVirtBnode((BNode) object).getSkolemId());
+		}
+
+		// Override blank node subjects to be a skolemized IRI
+		if (subject != null && subject instanceof BNode) {
+			subject = new UriRef(toVirtBnode((BNode) subject).getSkolemId());
+		}
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("performFilter(UriRef graph, NonLiteral s, UriRef p, Resource o)");
+			logger.debug(" > g: {}", graph);
+			logger.debug(" > s: {}", subject);
+			logger.debug(" > p: {}", predicate);
+			logger.debug(" > o: {}", object);
+		}
+
+		List<Triple> list = null;
+		Exception e = null;
+		Set<String> filters = new HashSet<String>(Arrays.asList(filterQueries));
+
+		//
+		if (subject == null) {
+			filters.remove(SELECT_TRIPLES_S_P_O);
+			filters.remove(SELECT_TRIPLES_S_NULL_NULL);
+			filters.remove(SELECT_TRIPLES_S_P_NULL);
+			filters.remove(SELECT_TRIPLES_S_NULL_O);
+		} else {
+			filters.remove(SELECT_TRIPLES_NULL_NULL_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_NULL_O);
+			filters.remove(SELECT_TRIPLES_NULL_P_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_P_O);
+		}
+		if (predicate == null) {
+			filters.remove(SELECT_TRIPLES_S_P_O);
+			filters.remove(SELECT_TRIPLES_NULL_P_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_P_O);
+			filters.remove(SELECT_TRIPLES_S_P_NULL);
+		} else {
+			filters.remove(SELECT_TRIPLES_S_NULL_O);
+			filters.remove(SELECT_TRIPLES_NULL_NULL_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_NULL_O);
+			filters.remove(SELECT_TRIPLES_S_NULL_NULL);
+		}
+		if (object == null) {
+			filters.remove(SELECT_TRIPLES_S_P_O);
+			filters.remove(SELECT_TRIPLES_S_NULL_O);
+			filters.remove(SELECT_TRIPLES_NULL_P_O);
+			filters.remove(SELECT_TRIPLES_NULL_NULL_O);
+		} else {
+			filters.remove(SELECT_TRIPLES_S_P_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_NULL_NULL);
+			filters.remove(SELECT_TRIPLES_NULL_P_NULL);
+			filters.remove(SELECT_TRIPLES_S_NULL_NULL);
+		}
+
+		// There must be only 1 boss
+		String filter = filters.iterator().next();
+		PreparedStatement ps = null;
+		VirtuosoResultSet rs = null;
+		try {
+			logger.debug("query: {}", filter);
+			ps = getStatement(filter);
+			// In any case the first binding is the graph
+			bindGraph(ps, 1, graph);
+
+			int index = 2;
+			if (subject != null) {
+				bindSubject(ps, index, subject);
+				index++;
+			}
+			if (predicate != null) {
+				bindPredicate(ps, index, predicate);
+				index++;
+			}
+			if (object != null) {
+				bindValue(ps, index, object);
+			}
+
+			rs = (VirtuosoResultSet) ps.executeQuery();
+			list = new ArrayList<Triple>();
+
+			while (rs.next()) {
+				list.add(new TripleBuilder(rs.getObject(1), rs.getObject(2), rs
+						.getObject(3)).build());
+			}
+		} catch (VirtuosoException e1) {
+			logger.error("ERROR while executing statement", ps);
+			e = e1;
+		} catch (SQLException e1) {
+			logger.error("ERROR while executing statement", ps);
+			e = e1;
+		} finally {
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Throwable ex) {
+				logger.error("Cannot close result set", ex);
+			}
+		}
+
+		if (list == null || e != null) {
+			throw new RuntimeException(e);
+		}
+		return list.iterator();
+	}
+
+	public int size(String graph){
+		Exception e = null;
+		PreparedStatement ps = null;
+		VirtuosoResultSet rs = null;
+		int size = -1;
+		try {
+			ps = getStatement(COUNT_TRIPLES_OF_GRAPH);
+			// In any case the first binding is the graph
+			bindGraph(ps, 1, graph);
+			ps.execute();
+			rs = (VirtuosoResultSet) ps.getResultSet();
+			rs.next();
+			size = rs.getInt(1);
+		} catch (VirtuosoException e1) {
+			logger.error("ERROR while executing statement", ps);
+			e = e1;
+		} catch (SQLException e1) {
+			logger.error("ERROR while executing statement", ps);
+			e = e1;
+		} finally {
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Throwable ex) {
+				logger.error("Cannot close result set", ex);
+			}
+		}
+		if (size == -1 || e != null) {
+			throw new RuntimeException(e);
+		}
+		return size;	
+	}
+	
+	/**
+	 * 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;
+		}
+
+		private NonLiteral buildSubject() {
+			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 DataAccess.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");
+			}
+		}
+
+		private UriRef buildPredicate() {
+			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");
+			}
+		}
+
+		Resource buildObject() {
+			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 DataAccess.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;
+				if (rb.rb_box.getClass().isAssignableFrom(String.class)) {
+					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 (rb.rb_box instanceof VirtuosoExtendedString) {
+					VirtuosoExtendedString vs = (VirtuosoExtendedString) rb.rb_box;
+
+					if (vs.iriType == VirtuosoExtendedString.IRI
+							&& (vs.strType & 0x01) == 0x01) {
+						// Is IRI
+						return new UriRef(vs.str);
+					} else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+						//
+						return DataAccess.this.toBNode(vs.str);
+					} else {
+						String type = rb.getType();
+						if (type == null) {
+							String lang = rb.getLang();
+							if (lang != null) {
+								return new PlainLiteralImpl(vs.str,
+										new Language(lang));
+							}
+							// Is a plain literal
+							return new PlainLiteralImpl(vs.str);
+						} else {
+							return new TypedLiteralImpl(vs.str,
+									new UriRef(type));
+						}
+					}
+				}
+			} else if (o == null) {
+				// Raise an exception
+				throw new IllegalStateException("Object cannot be NULL!");
+			}
+
+			// FIXME (not clear this...)
+			return new PlainLiteralImpl(o.toString());
+		}
+
+		public Triple build() {
+			logger.debug("TripleBuilder.build()");
+			return new TripleImpl(buildSubject(), buildPredicate(),
+					buildObject());
+		}
+	}
+
+	/**
+	 * The following private methods are used to support the triple addition
+	 * plan B
+	 */
+	
+	public boolean performAddPlanB(String graph, Triple triple) {
+
+		StringBuilder b = new StringBuilder();
+		b.append(toVirtSubject(triple.getSubject())).append(" ")
+				.append(toVirtPredicate(triple.getPredicate())).append(" ")
+				.append(toVirtObject(triple.getObject())).append(" . ");
+		String sql = new StringBuilder().append("db.dba.ttlp(?, '', '").append(graph).append("', 0)").toString();
+		logger.debug("Exec Plan B: {}", sql);
+		Exception e = null;
+		PreparedStatement st = null;
+		try {
+			st = getStatement(sql);
+			String s = b.toString();
+			logger.trace(" TTL is \n{}\n", s);
+			st.setNString(1, b.toString());
+			st.execute();
+		} catch (VirtuosoException ve) {
+			logger.error("ERROR while executing statement", ve);
+			e = ve;
+		} catch (SQLException se) {
+			logger.error("ERROR while executing statement", se);
+			e = se;
+		}
+		if (e != null) {
+			logger.error("S {}", triple.getSubject());
+			logger.error("P {}", triple.getPredicate());
+			logger.error("O {}", triple.getObject());
+			logger.error(" O length: {}", triple.getObject().toString()
+					.length());
+			logger.error("Sql: {}", sql);
+			throw new RuntimeException(e);
+		}
+		return true;
+	}
+
+	/**
+	 * Returns a string to be used inline 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).asSkolemIri();
+		} else if (object instanceof PlainLiteral) {
+			return toVirtPlainLiteral((PlainLiteral) object);
+		} else if (object instanceof TypedLiteral) {
+			return toVirtTypedLiteral((TypedLiteral) object);
+		}
+		// XXX throw exception here?
+		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();// .replaceAll("\"", "\\\\\"");
+		StringBuilder prepared;
+		// If XMLLiteral, prepare XML entities
+		prepared = prepareString(
+				literal,
+				dt.getUnicodeString()
+						.equals("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"));
+		return new StringBuilder().append('"').append('"').append('"')
+				.append(prepared).append('"').append('"').append('"')
+				.append("^^").append(toVirtIri(dt)).toString();
+	}
+
+	private StringBuilder prepareString(String str, boolean xml) {
+		StringBuilder retStr = new StringBuilder();
+		for (int i = 0; i < str.length(); i++) {
+			int cp = Character.codePointAt(str, i);
+			int charCount = Character.charCount(cp);
+			if (charCount > 1) {
+				i += charCount - 1; // 2.
+				if (i >= str.length()) {
+					throw new IllegalArgumentException("truncated unexpectedly");
+				}
+			}
+
+			if (cp < 128) {
+				retStr.appendCodePoint(cp);
+			} else {
+				if (xml) {
+					retStr.append(String.format("&#x%04x;", cp));
+				} else {
+					retStr.append(String.format("\\u%04x", cp));
+				}
+			}
+		}
+		return retStr;
+	}
+
+	/**
+	 * 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('"')
+				.append('"').append(prepareString(literal, false)).append('"')
+				.append('"').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).asSkolemIri();
+		} else {
+			// These should be the only 2 implementations
+			throw new IllegalArgumentException(
+					"subject must be BNode or UriRef");
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
new file mode 100644
index 0000000..f9ba786
--- /dev/null
+++ b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/org/apache/clerezza/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
@@ -0,0 +1,923 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.clerezza.rdf.virtuoso.storage.access;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+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.TcManager;
+import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
+import org.apache.clerezza.rdf.virtuoso.storage.VirtuosoGraph;
+import org.apache.clerezza.rdf.virtuoso.storage.VirtuosoMGraph;
+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.Properties;
+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 virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+import virtuoso.jdbc4.VirtuosoPreparedStatement;
+import virtuoso.jdbc4.VirtuosoResultSet;
+import virtuoso.jdbc4.VirtuosoStatement;
+
+/**
+ * A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} for
+ * Virtuoso.
+ * 
+ * @author enridaga
+ * 
+ */
+@Component(metatype = true, immediate = true)
+@Service(WeightedTcProvider.class)
+@Properties({
+		@Property(name = "password", value = "dba", description = "User password"),
+		@Property(name = "host", value = "localhost", description = "The host running the Virtuoso server"),
+		@Property(name = "port", intValue = 1111, description = "The port number"),
+		@Property(name = "user", value = "dba", description = "User name"),
+		@Property(name = "weight", intValue = 110, description = "Weight assigned to this provider"),
+		@Property(name = TcManager.GENERAL_PURPOSE_TC, boolValue = true) })
+public class VirtuosoWeightedProvider implements WeightedTcProvider {
+
+	// JDBC driver class (XXX move to DataAccess?)
+	public static final String DRIVER = "virtuoso.jdbc4.Driver";
+
+	// Default value for the property "weight"
+	public static final int DEFAULT_WEIGHT = 110;
+
+	// Names of properties in OSGi configuration
+	public static final String HOST = "host";
+	public static final String PORT = "port";
+	public static final String USER = "user";
+	public static final String PASSWORD = "password";
+	public static final String WEIGHT = "weight";
+
+	// Name of the graph used to contain the registry of the created graphs
+	public static final String ACTIVE_GRAPHS_GRAPH = "urn:x-virtuoso:active-graphs";
+
+	// Loaded graphs
+	private Map<UriRef, VirtuosoMGraph> graphs = new HashMap<UriRef, VirtuosoMGraph>();
+
+	// DataAccess registry
+	private Set<DataAccess> dataAccessSet = new HashSet<DataAccess>();
+
+	// Logger
+	private Logger logger = LoggerFactory
+			.getLogger(VirtuosoWeightedProvider.class);
+
+	// Fields
+	private String host;
+	private Integer port;
+	private String user;
+	private String pwd;
+	private String connStr;
+	private int weight = DEFAULT_WEIGHT;
+
+	/**
+	 * 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.");
+	}
+
+	public VirtuosoWeightedProvider(String jdbcConnectionString,
+			String jdbcUser, String jdbcPassword) {
+		connStr = jdbcConnectionString;
+		user = jdbcUser;
+		pwd = jdbcPassword;
+	}
+
+	/**
+	 * 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.trace("activate(ComponentContext {})", cCtx);
+		logger.info("Activating VirtuosoWeightedProvider...");
+
+		if (cCtx == 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 {
+
+				// Bind logging of DriverManager
+				if (logger.isDebugEnabled()) {
+					logger.debug("Activating logging for DriverManager");
+					// DriverManager.setLogWriter(new PrintWriter(System.err));
+					DriverManager.setLogWriter(new PrintWriter(new Writer() {
+						private Logger l = LoggerFactory
+								.getLogger(DriverManager.class);
+						private StringBuilder b = new StringBuilder();
+
+						@Override
+						public void write(char[] cbuf, int off, int len)
+								throws IOException {
+							b.append(cbuf, off, len);
+						}
+
+						@Override
+						public void flush() throws IOException {
+							l.debug("{}", b.toString());
+							b = new StringBuilder();
+						}
+
+						@Override
+						public void close() throws IOException {
+							l.debug("{}", b.toString());
+							l.debug("Log PrintWriter closed");
+						}
+					}));
+				}
+
+				// 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
+				 */
+				host = (String) cCtx.getProperties().get(HOST);
+				port = (Integer) cCtx.getProperties().get(PORT);
+				user = (String) cCtx.getProperties().get(USER);
+				pwd = (String) cCtx.getProperties().get(PASSWORD);
+
+				// Build connection string
+				connStr = getConnectionString(host, port);
+
+				// Check connection
+				VirtuosoConnection connection = getConnection(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);
+
+				// everything went ok
+				connection.close();
+			} 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());
+			}
+		}
+		// Load remembered graphs
+		Set<UriRef> remembered = readRememberedGraphs();
+		for (UriRef name : remembered) {
+			if (canModify(name)) {
+				graphs.put(name, new VirtuosoMGraph(name.getUnicodeString(),
+						createDataAccess()));
+			} else {
+				graphs.put(name, new VirtuosoGraph(name.getUnicodeString(),
+						createDataAccess()));
+			}
+		}
+		logger.info("Activated VirtuosoWeightedProvider.");
+	}
+
+	public static final String getConnectionString(String hostName,
+			Integer portNumber) {
+		return new StringBuilder().append("jdbc:virtuoso://").append(hostName)
+				.append(":").append(portNumber).append("/CHARSET=UTF-8")
+				.toString();
+	}
+
+	private Set<UriRef> readRememberedGraphs() {
+		logger.trace(" readRememberedGraphs()");
+		String SQL = "SPARQL SELECT DISTINCT ?G FROM <" + ACTIVE_GRAPHS_GRAPH
+				+ "> WHERE { ?G a <urn:x-virtuoso/active-graph> }";
+		VirtuosoConnection connection = null;
+		Exception e = null;
+		VirtuosoStatement st = null;
+		VirtuosoResultSet rs = null;
+		Set<UriRef> remembered = new HashSet<UriRef>();
+		try {
+			connection = getConnection();
+			st = (VirtuosoStatement) connection.createStatement();
+			logger.debug("Executing SQL: {}", SQL);
+			rs = (VirtuosoResultSet) st.executeQuery(SQL);
+			while (rs.next()) {
+				UriRef name = new UriRef(rs.getString(1));
+				logger.debug(" > Graph {}", name);
+				remembered.add(name);
+			}
+		} catch (VirtuosoException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} catch (SQLException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} catch (ClassNotFoundException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} finally {
+
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Exception ex) {
+			}
+			;
+			try {
+				if (st != null)
+					st.close();
+			} catch (Exception ex) {
+			}
+			;
+			if (connection != null) {
+				try {
+					connection.close();
+				} catch (VirtuosoException e1) {
+					logger.error("Cannot close connection", e1);
+				}
+			}
+		}
+		if (e != null) {
+			throw new RuntimeException(e);
+		}
+		return remembered;
+	}
+
+	private void rememberGraphs(UriRef... graphs) {
+		logger.trace(" saveActiveGraphs()");
+		if (graphs.length > 0) {
+			// Returns the list of graphs in the virtuoso quad store
+			String SQL = "SPARQL INSERT INTO <" + ACTIVE_GRAPHS_GRAPH
+					+ "> { `iri(??)` a <urn:x-virtuoso/active-graph> }";
+			VirtuosoConnection connection = null;
+			Exception e = null;
+			VirtuosoPreparedStatement st = null;
+			VirtuosoResultSet rs = null;
+			try {
+				try {
+					connection = getConnection();
+					connection.setAutoCommit(false);
+					st = (VirtuosoPreparedStatement) connection
+							.prepareStatement(SQL);
+					logger.debug("Executing SQL: {}", SQL);
+					for (UriRef u : graphs) {
+						logger.trace(" > remembering {}", u);
+						st.setString(1, u.getUnicodeString());
+						st.executeUpdate();
+					}
+					connection.commit();
+				} catch (Exception e1) {
+					logger.error("Error while executing query/connection.", e1);
+					e = e1;
+					connection.rollback();
+				}
+			} catch (SQLException e1) {
+				logger.error("Error while executing query/connection.", e1);
+				e = e1;
+			} finally {
+				try {
+					if (rs != null)
+						rs.close();
+				} catch (Exception ex) {
+				}
+				;
+				try {
+					if (st != null)
+						st.close();
+				} catch (Exception ex) {
+				}
+				;
+				if (connection != null) {
+					try {
+						connection.close();
+					} catch (VirtuosoException e1) {
+						logger.error("Cannot close connection", e1);
+					}
+				}
+			}
+			if (e != null) {
+				throw new RuntimeException(e);
+			}
+		}
+	}
+
+	private void forgetGraphs(UriRef... graphs) {
+		logger.trace(" forgetGraphs()");
+		if (graphs.length > 0) {
+			// Returns the list of graphs in the virtuoso quad store
+			String SQL = "SPARQL WITH <"
+					+ ACTIVE_GRAPHS_GRAPH
+					+ "> DELETE { ?s ?p ?v } WHERE { ?s ?p ?v . FILTER( ?s = iri(??) ) }";
+			VirtuosoConnection connection = null;
+			Exception e = null;
+			VirtuosoPreparedStatement st = null;
+			VirtuosoResultSet rs = null;
+			try {
+				try {
+					connection = getConnection();
+					connection.setAutoCommit(false);
+					st = (VirtuosoPreparedStatement) connection
+							.prepareStatement(SQL);
+					logger.debug("Executing SQL: {}", SQL);
+					for (UriRef u : graphs) {
+						logger.trace(" > remembering {}", u);
+						st.setString(1, u.getUnicodeString());
+						st.executeUpdate();
+					}
+					connection.commit();
+				} catch (Exception e1) {
+					logger.error("Error while executing query/connection.", e1);
+					e = e1;
+					connection.rollback();
+				}
+			} catch (SQLException e1) {
+				logger.error("Error while executing query/connection.", e1);
+				e = e1;
+			} finally {
+				try {
+					if (rs != null)
+						rs.close();
+				} catch (Exception ex) {
+				}
+				;
+				try {
+					if (st != null)
+						st.close();
+				} catch (Exception ex) {
+				}
+				;
+				if (connection != null) {
+					try {
+						connection.close();
+					} catch (VirtuosoException e1) {
+						logger.error("Cannot close connection", e1);
+					}
+				}
+			}
+			if (e != null) {
+				throw new RuntimeException(e);
+			}
+		}
+	}
+
+	/**
+	 * Deactivates this component.
+	 * 
+	 * @param cCtx
+	 *            component context provided by OSGi
+	 */
+	@Deactivate
+	public void deactivate(ComponentContext cCtx) {
+		logger.debug("deactivate(ComponentContext {})", cCtx);
+		// Save active (possibly empty) graphs to a dedicated graph
+		rememberGraphs();
+		// XXX Important. Close all opened resources
+		for (DataAccess mg : dataAccessSet) {
+			mg.close();
+		}
+
+		logger.info("Shutdown complete.");
+	}
+
+	public VirtuosoConnection getConnection() throws SQLException,
+			ClassNotFoundException {
+		return getConnection(connStr, user, pwd);
+	}
+
+	private VirtuosoConnection getConnection(String connStr, String user,
+			String pwd) throws SQLException, ClassNotFoundException {
+		logger.debug("getConnection(String {}, String {}, String *******)",
+				connStr, user);
+		/**
+		 * FIXME For some reasons, it looks the DriverManager is instantiating a
+		 * new virtuoso.jdbc4.Driver instance upon any activation. (Enable DEBUG
+		 * to see this)
+		 */
+		logger.debug("Loading JDBC Driver");
+		Class.forName(VirtuosoWeightedProvider.DRIVER, true, this.getClass()
+				.getClassLoader());
+		VirtuosoConnection c = (VirtuosoConnection) DriverManager
+				.getConnection(connStr, user, pwd);
+		c.setAutoCommit(true);
+		return c;
+	}
+
+	/**
+	 * 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.
+	 * 
+	 * 
+	 * @param name
+	 * @return
+	 */
+	private VirtuosoMGraph loadGraphOnce(UriRef name) {
+		logger.debug("loadGraphOnce({})", name);
+
+		// Check whether the graph have been already loaded once
+		if (graphs.containsKey(name)) {
+			logger.debug("{} is already loaded", name);
+			return graphs.get(name);
+		} else {
+			VirtuosoMGraph graph = null;
+			logger.debug("Attempt to load {}", name);
+			// Let's create the graph object
+			String SQL = "SPARQL SELECT ?G WHERE { GRAPH ?G {[] [] []} . FILTER(?G = "
+					+ name + ")} LIMIT 1";
+
+			Statement st = null;
+			VirtuosoResultSet rs = null;
+			VirtuosoConnection connection = null;
+			Exception e = null;
+			try {
+				connection = getConnection(connStr, user, pwd);
+				st = connection.createStatement();
+				logger.debug("Executing SQL: {}", SQL);
+				st.execute(SQL);
+				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(),
+										createDataAccess()));
+					} else {
+						logger.debug("Creating read-only Graph for graph {}",
+								name);
+						graphs.put(name,
+								new VirtuosoMGraph(name.getUnicodeString(),
+										createDataAccess()).asVirtuosoGraph());
+					}
+					graph = graphs.get(name);
+				}
+
+			} catch (VirtuosoException ve) {
+				logger.error("Error while executing query/connection.", ve);
+				e = ve;
+			} catch (SQLException se) {
+				logger.error("Error while executing query/connection.", se);
+				e = se;
+			} catch (ClassNotFoundException ce) {
+				logger.error("Error while executing query/connection.", ce);
+				e = ce;
+			} finally {
+				try {
+					if (rs != null)
+						rs.close();
+				} catch (Exception ex) {
+				}
+				;
+				try {
+					if (st != null)
+						st.close();
+				} catch (Exception ex) {
+				}
+				;
+				if (connection != null) {
+					try {
+						connection.close();
+					} catch (VirtuosoException e1) {
+						logger.error("Cannot close connection", e1);
+					}
+				}
+			}
+			if (e != null) {
+				throw new RuntimeException(e);
+			}
+			return graph;
+		}
+
+	}
+
+	public DataAccess createDataAccess() {
+		DataAccess da = new DataAccess(connStr, user, pwd);
+		dataAccessSet.add(da);
+		// Remember all opened ones
+		return da;
+	}
+
+	/**
+	 * 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>();
+		// XXX Add the active (possibly empty) mgraphs
+		graphs.addAll(this.graphs.keySet());
+		// Returns the list of graphs in the virtuoso quad store
+		String SQL = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {[] [] []} }";
+		VirtuosoConnection connection = null;
+		Exception e = null;
+		VirtuosoStatement st = null;
+		VirtuosoResultSet rs = null;
+		try {
+			connection = getConnection();
+			st = (VirtuosoStatement) connection.createStatement();
+			logger.debug("Executing SQL: {}", SQL);
+			rs = (VirtuosoResultSet) st.executeQuery(SQL);
+			while (rs.next()) {
+				UriRef graph = new UriRef(rs.getString(1));
+				logger.debug(" > Graph {}", graph);
+				graphs.add(graph);
+			}
+		} catch (VirtuosoException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} catch (SQLException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} catch (ClassNotFoundException e1) {
+			logger.error("Error while executing query/connection.", e1);
+			e = e1;
+		} finally {
+
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Exception ex) {
+			}
+			;
+			try {
+				if (st != null)
+					st.close();
+			} catch (Exception ex) {
+			}
+			;
+			if (connection != null) {
+				try {
+					connection.close();
+				} catch (VirtuosoException e1) {
+					logger.error("Cannot close connection", e1);
+				}
+			}
+		}
+		if (e != null) {
+			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) {
+		VirtuosoConnection connection = null;
+		ResultSet rs = null;
+		Statement st = null;
+		logger.debug("getPermissions(String {})", graph);
+		Exception e = null;
+		Long result = null;
+		try {
+			connection = getConnection();
+			String sql = "SELECT DB.DBA.RDF_GRAPH_USER_PERMS_GET ('" + graph
+					+ "','" + connection.getMetaData().getUserName() + "') ";
+			logger.debug("Executing SQL: {}", sql);
+			st = connection.createStatement();
+			st.execute(sql);
+			rs = st.getResultSet();
+			rs.next();
+			result = rs.getLong(1);
+			logger.debug("Permission: {}", result);
+		} catch (VirtuosoException ve) {
+			logger.error("A virtuoso SQL exception occurred.");
+			e = ve;
+		} catch (SQLException se) {
+			logger.error("An SQL exception occurred.");
+			e = se;
+		} catch (ClassNotFoundException e1) {
+			logger.error("An ClassNotFoundException occurred.");
+			e = e1;
+		} finally {
+			try {
+				if (rs != null)
+					rs.close();
+			} catch (Exception ex) {
+			}
+			;
+			try {
+				if (st != null)
+					st.close();
+			} catch (Exception ex) {
+			}
+			;
+			if (connection != null) {
+				try {
+					connection.close();
+				} catch (VirtuosoException e1) {
+					logger.error("Cannot close connection", e1);
+				}
+			}
+		}
+		if (e != null) {
+			throw new RuntimeException(e);
+		}
+		return result;
+	}
+
+	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(),
+						createDataAccess()));
+				rememberGraphs(name);
+				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);
+			forgetGraphs(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;
+	}
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoBNode.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoBNode.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoBNode.java
deleted file mode 100644
index d73d784..0000000
--- a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoBNode.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package rdf.virtuoso.storage;
-
-import org.apache.clerezza.rdf.core.BNode;
-
-public class VirtuosoBNode extends BNode {
-	private String skolemId;
-	public VirtuosoBNode(String skolemId) {
-		this.skolemId = skolemId;
-	}
-	
-	public String getSkolemId(){
-		return skolemId;
-	}
-	
-	public String asSkolemIri(){
-		return new StringBuilder().append('<').append(skolemId).append('>').toString();
-	}
-	
-	public String toString(){
-		return skolemId;
-	}
-	
-	@Override
-	public boolean equals(Object obj) {
-		return (obj instanceof VirtuosoBNode) && (obj.toString().equals(toString()));
-	}
-}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
deleted file mode 100644
index ada5779..0000000
--- a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package 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 rdf.virtuoso.storage.access.DataAccess;
-
-/**
- * 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, DataAccess dataAccess) {
-		super(name, dataAccess);
-	}
-
-	@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;
-	}
-}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/25694741/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
----------------------------------------------------------------------
diff --git a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java b/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
deleted file mode 100644
index 4d876c4..0000000
--- a/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package rdf.virtuoso.storage;
-
-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.Graph;
-import org.apache.clerezza.rdf.core.Literal;
-import org.apache.clerezza.rdf.core.MGraph;
-import org.apache.clerezza.rdf.core.NonLiteral;
-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.access.LockableMGraph;
-import org.apache.clerezza.rdf.core.impl.AbstractMGraph;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import rdf.virtuoso.storage.access.DataAccess;
-
-/**
- * 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();
-
-	/**
-	 * Logger
-	 */
-	protected Logger logger = LoggerFactory.getLogger(VirtuosoMGraph.class);
-
-	/**
-	 * The name of the graph
-	 */
-	private String name = null;
-	// private int size = 0;
-
-	private VirtuosoGraph readOnly = null;
-	private DataAccess dataAccess = null;
-
-	/**
-	 * Creates a {@link VirtuosoMGraph} Virtuoso MGraph binds directly to the
-	 * store.
-	 * 
-	 * @param connection
-	 */
-	public VirtuosoMGraph(String name, DataAccess dataAccess) {
-		logger.debug("VirtuosoMGraph(String {}, DataAccess {})", name,
-				dataAccess);
-		this.name = name;
-		// this.provider = provider;
-		this.dataAccess = dataAccess;
-	}
-
-	@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, getDataAccess());
-		}
-		return readOnly;
-	}
-
-	protected DataAccess getDataAccess() {
-		return this.dataAccess;
-	}
-
-	@Override
-	protected Iterator<Triple> performFilter(NonLiteral subject,
-			UriRef predicate, Resource object) {
-		readLock.lock();
-		Iterator<Triple> tit = getDataAccess().filter(getName(), subject,
-				predicate, object);
-		readLock.unlock();
-		return tit;
-	}
-
-	/**
-	 * We load the size every time it is requested.
-	 */
-	@Override
-	public int size() {
-		logger.debug("size()");
-		readLock.lock();
-		int size = getDataAccess().size(getName());
-		readLock.unlock();
-		return size;
-	}
-
-	@Override
-	public void clear() {
-		logger.debug("clear()");
-		writeLock.lock();
-		getDataAccess().clearGraph(getName());
-		writeLock.unlock();
-	}
-
-	protected boolean performAdd(Triple triple) {
-		logger.debug("performAdd(Triple {})", triple);
-
-		// If the object is a very long literal we use plan B
-		// Reason:
-		// Virtuoso Error:
-		// SR449: Key is too long, index RDF_QUAD, ruling part is 1901 bytes
-		// that exceeds 1900 byte limit
-		// We use alternative method for literals
-		writeLock.lock();
-		if (triple.getObject() instanceof Literal) {
-			getDataAccess().performAddPlanB(getName(), triple);
-		}else{
-			getDataAccess().insertQuad(getName(), triple);
-		}
-		writeLock.unlock();
-		return true;
-	}
-
-	protected boolean performRemove(Triple triple) {
-		logger.debug("performRemove(Triple triple)", triple);
-		writeLock.lock();
-		getDataAccess().deleteQuad(getName(), triple);
-		writeLock.unlock();
-		return true;
-	}
-
-	/**
-	 * Returns the graph name
-	 * 
-	 * @return
-	 */
-	public String getName() {
-		logger.debug("getName()");
-		return name;
-	}
-
-	/**
-	 * 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;
-	}
-}


Mime
View raw message