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 2014/03/16 19:51:38 UTC
[4/5] git commit: CLEREZZA-810 Packages renamed
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 <en...@apache.org>
Authored: Sun Mar 16 18:49:16 2014 +0000
Committer: enridaga <en...@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;
- }
-}