You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by ha...@apache.org on 2019/02/03 17:37:27 UTC
[clerezza] 02/02: CLEREZZA-1031: Move rdf.core access to a new
module called dataset
This is an automated email from the ASF dual-hosted git repository.
hasan pushed a commit to branch reunited
in repository https://gitbox.apache.org/repos/asf/clerezza.git
commit 50211e4260e2b30e4b36ea95be29f3bbbb1fc811
Author: Hasan <ha...@apache.org>
AuthorDate: Sun Feb 3 18:36:35 2019 +0100
CLEREZZA-1031: Move rdf.core access to a new module called dataset
---
dataset/pom.xml | 114 ++++
.../dataset/EntityAlreadyExistsException.java | 50 ++
.../dataset/EntityUndeletableException.java | 50 ++
.../dataset/ImmutableGraphServiceFactory.java | 58 ++
.../clerezza/dataset/MGraphServiceFactory.java | 54 ++
.../clerezza/dataset/NoSuchEntityException.java | 51 ++
.../clerezza/dataset/QueryableTcProvider.java | 41 ++
.../org/apache/clerezza/dataset/SecuredGraph.java | 191 +++++++
.../org/apache/clerezza/dataset/TcManager.java | 613 +++++++++++++++++++++
.../org/apache/clerezza/dataset/TcProvider.java | 151 +++++
.../clerezza/dataset/TcProviderMultiplexer.java | 446 +++++++++++++++
.../dataset/WeightedProviderComparator.java | 41 ++
.../clerezza/dataset/WeightedTcProvider.java | 36 ++
.../java/org/apache/clerezza/dataset/package.html | 56 ++
.../dataset/security/TcAccessController.java | 342 ++++++++++++
.../clerezza/dataset/security/TcPermission.java | 149 +++++
.../org/apache/clerezza/dataset/SecurityTest.java | 175 ++++++
.../org/apache/clerezza/dataset/TcManagerTest.java | 299 ++++++++++
.../clerezza/dataset/providers/WeightedA.java | 103 ++++
.../clerezza/dataset/providers/WeightedA1.java | 103 ++++
.../clerezza/dataset/providers/WeightedAHeavy.java | 101 ++++
.../clerezza/dataset/providers/WeightedBlight.java | 106 ++++
.../clerezza/dataset/providers/WeightedDummy.java | 155 ++++++
23 files changed, 3485 insertions(+)
diff --git a/dataset/pom.xml b/dataset/pom.xml
new file mode 100644
index 0000000..3ce095f
--- /dev/null
+++ b/dataset/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+
+ 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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.clerezza</groupId>
+ <artifactId>clerezza</artifactId>
+ <version>8-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>dataset</artifactId>
+ <packaging>bundle</packaging>
+ <version>8-SNAPSHOT</version>
+ <name>Clerezza - DataSet</name>
+ <description>Interfaces and utilities to access RDF Graphs</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.clerezza</groupId>
+ <artifactId>api</artifactId>
+ <version>8-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.clerezza</groupId>
+ <artifactId>api.impl</artifactId>
+ <version>8-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.clerezza</groupId>
+ <artifactId>sparql</artifactId>
+ <version>8-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.ds-annotations</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.clerezza</groupId>
+ <artifactId>utils</artifactId>
+ <version>0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>org.apache.clerezza.dataset.*</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-scr-scrdescriptor</id>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/EntityAlreadyExistsException.java b/dataset/src/main/java/org/apache/clerezza/dataset/EntityAlreadyExistsException.java
new file mode 100644
index 0000000..15dcb56
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/EntityAlreadyExistsException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.IRI;
+
+/**
+ * is thrown on an attempt to create an entity with a name which already exists
+ *
+ * @author hasan
+ */
+public class EntityAlreadyExistsException extends RuntimeException {
+
+ private IRI entityName;
+
+ /**
+ * creates an exception indicating that an entity with the specified name
+ * already exists.
+ *
+ * @param entityName the name of the entity which already exists
+ */
+ public EntityAlreadyExistsException(IRI entityName) {
+ super("An entity with this name already exists: "+entityName);
+ this.entityName = entityName;
+ }
+
+ /**
+ *
+ * @return the name of the entity which already exists
+ */
+ public IRI getEntityName() {
+ return entityName;
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/EntityUndeletableException.java b/dataset/src/main/java/org/apache/clerezza/dataset/EntityUndeletableException.java
new file mode 100644
index 0000000..32c5088
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/EntityUndeletableException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.IRI;
+
+/**
+ * is thrown on an attempt to delete an entity with a provider that
+ * supports the delete operation when the specified entity cannot be deleted
+ *
+ * @author reto
+ */
+public class EntityUndeletableException extends RuntimeException {
+ private IRI entityName;
+
+ /**
+ * creates an exception indicating that the entity with the specified name
+ * cannot be deleted
+ *
+ * @param entityName the name of the entity which is undeletable
+ */
+ public EntityUndeletableException(IRI entityName) {
+ super("This entity is undeletable: "+entityName);
+ this.entityName = entityName;
+ }
+
+ /**
+ *
+ * @return the name of the entity which is undeletable
+ */
+ public IRI getEntityName() {
+ return entityName;
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/ImmutableGraphServiceFactory.java b/dataset/src/main/java/org/apache/clerezza/dataset/ImmutableGraphServiceFactory.java
new file mode 100644
index 0000000..b775d82
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/ImmutableGraphServiceFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.dataset.security.TcAccessController;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @see <a href="http://www.osgi.org/javadoc/r4v41/org/osgi/framework/ServiceFactory.html">
+ * Interface ServiceFactory</a>
+ *
+ * @author mir
+ */
+public class ImmutableGraphServiceFactory implements ServiceFactory {
+
+ private final TcManager tcManager;
+ private final IRI name;
+ private final TcAccessController tcAccessController;
+
+ ImmutableGraphServiceFactory(TcManager tcManager, IRI name,
+ TcAccessController tcAccessController) {
+ this.tcManager = tcManager;
+ this.name = name;
+ this.tcAccessController = tcAccessController;
+ }
+
+ @Override
+ public Object getService(Bundle arg0, ServiceRegistration arg1) {
+ Graph tc =
+ new SecuredGraph(tcManager.getImmutableGraph(name), name,
+ tcAccessController);
+ return tc.getImmutableGraph();
+ }
+
+ @Override
+ public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2) {
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/MGraphServiceFactory.java b/dataset/src/main/java/org/apache/clerezza/dataset/MGraphServiceFactory.java
new file mode 100644
index 0000000..cf3435c
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/MGraphServiceFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.dataset.security.TcAccessController;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @see <a href="http://www.osgi.org/javadoc/r4v41/org/osgi/framework/ServiceFactory.html">
+ * Interface ServiceFactory</a>
+ *
+ * @author mir
+ */
+public class MGraphServiceFactory implements ServiceFactory {
+
+ private TcManager tcManager;
+ private IRI name;
+ private final TcAccessController tcAccessController;
+
+ MGraphServiceFactory(TcManager tcManager, IRI name,
+ TcAccessController tcAccessController) {
+ this.tcManager = tcManager;
+ this.name = name;
+ this.tcAccessController = tcAccessController;
+ }
+
+ @Override
+ public Object getService(Bundle arg0, ServiceRegistration arg1) {
+ return new SecuredGraph(tcManager.getMGraph(name), name, tcAccessController);
+ }
+
+ @Override
+ public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2) {
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/NoSuchEntityException.java b/dataset/src/main/java/org/apache/clerezza/dataset/NoSuchEntityException.java
new file mode 100644
index 0000000..789dc6b
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/NoSuchEntityException.java
@@ -0,0 +1,51 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.IRI;
+
+/**
+ * is thrown on an attempt to perform an operation on an entity (i.e. a
+ * <code>ImmutableGraph</code> or <code>Graph</code> that does not exist.
+ *
+ * @author reto
+ */
+public class NoSuchEntityException extends RuntimeException {
+ private IRI entityName;
+
+ /**
+ * creates an exception indicating that the entity with the specified name
+ * does not exist.
+ *
+ * @param entityName the name for which no entity exists
+ */
+ public NoSuchEntityException(IRI entityName) {
+ super("No such entity: "+entityName);
+ this.entityName = entityName;
+ }
+
+ /**
+ * the name for which no entity exists.
+ *
+ * @return the name of the entity that doesn't exist
+ */
+ public IRI getEntityName() {
+ return entityName;
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/QueryableTcProvider.java b/dataset/src/main/java/org/apache/clerezza/dataset/QueryableTcProvider.java
new file mode 100644
index 0000000..0490a4c
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/QueryableTcProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.IRI;
+
+/**
+ * Extends the TcProvider interface for providers that support sparql queries.
+ */
+public interface QueryableTcProvider extends TcProvider {
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query.
+ *
+ * @param query
+ * the sparql query to execute
+ * @param defaultGraph
+ * the default ImmutableGraph against which to execute the query if not
+ * FROM clause is present
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ */
+ public Object executeSparqlQuery(String query, IRI defaultGraphUri);
+
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/SecuredGraph.java b/dataset/src/main/java/org/apache/clerezza/dataset/SecuredGraph.java
new file mode 100644
index 0000000..afc2102
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/SecuredGraph.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.dataset;
+
+import org.apache.clerezza.api.*;
+import org.apache.clerezza.api.impl.graph.SimpleImmutableGraph;
+import org.apache.clerezza.api.impl.graph.WriteBlockedGraph;
+import org.apache.clerezza.dataset.security.TcAccessController;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReadWriteLock;
+
+/**
+ * A Secured triple collection wraps a triple collection checking each access
+ * for the rights on a the ImmutableGraph for which the uri is passed to the
+ * constructor.
+ *
+ * @author mir, hasan
+ */
+public class SecuredGraph implements Graph {
+
+ private final Graph wrapped;
+ private final IRI name;
+ private final TcAccessController tcAccessController;
+
+ public SecuredGraph(Graph wrapped, IRI name,
+ TcAccessController tcAccessController) {
+ this.wrapped = wrapped;
+ this.name = name;
+ this.tcAccessController = tcAccessController;
+ }
+
+ @Override
+ public Iterator<Triple> filter(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
+ final Iterator<Triple> baseIter = wrapped.filter(subject, predicate, object);
+ return new Iterator<Triple>() {
+
+ @Override
+ public boolean hasNext() {
+ checkRead();
+ return baseIter.hasNext();
+ }
+
+ @Override
+ public Triple next() {
+ checkRead();
+ return baseIter.next();
+ }
+
+ @Override
+ public void remove() {
+ checkWrite();
+ baseIter.remove();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ checkRead();
+ return wrapped.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ checkRead();
+ return wrapped.isEmpty();
+ }
+
+ @Override
+ public Object[] toArray() {
+ checkRead();
+ return wrapped.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ checkRead();
+ return wrapped.toArray(a);
+ }
+
+ @Override
+ public boolean add(Triple e) {
+ checkWrite();
+ return wrapped.add(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ checkWrite();
+ return wrapped.remove(o);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Triple> c) {
+ checkWrite();
+ return wrapped.addAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ checkWrite();
+ return wrapped.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ checkWrite();
+ return wrapped.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ checkWrite();
+ wrapped.clear();
+ }
+
+ void checkRead() {
+ tcAccessController.checkReadPermission(name);
+ }
+
+ void checkWrite() {
+ tcAccessController.checkReadWritePermission(name);
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ checkRead();
+ return wrapped.contains((Triple) o);
+ }
+
+
+ @Override
+ public Iterator<Triple> iterator() {
+ return filter(null, null, null);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ checkRead();
+ return wrapped.containsAll(c);
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph() {
+ return new SimpleImmutableGraph(this);
+ }
+
+ @Override
+ public ReadWriteLock getLock() {
+ return wrapped.getLock();
+ }
+
+ /**
+ * Returns the wrapped Graph if the caller has all access rights.
+ * If the caller has only the read access right, then a write-blocked
+ * Graph is returned. If the caller has neither the read nor the write
+ * access right then an AccessControlException is thrown.
+ *
+ * @return the wrapped Graph or a write-block Graph depending
+ * on the access rights of the caller.
+ */
+ public Graph getUnsecuredGraph() {
+ try {
+ checkWrite();
+ return wrapped;
+ } catch (AccessControlException ex) {
+ checkRead();
+ return new WriteBlockedGraph(wrapped);
+ }
+
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/TcManager.java b/dataset/src/main/java/org/apache/clerezza/dataset/TcManager.java
new file mode 100644
index 0000000..8981ad3
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/TcManager.java
@@ -0,0 +1,613 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.graph.SimpleGraph;
+import org.apache.clerezza.api.impl.graph.WriteBlockedGraph;
+import org.apache.clerezza.dataset.security.TcAccessController;
+import org.apache.clerezza.sparql.*;
+import org.apache.clerezza.sparql.query.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+
+import java.security.AccessControlException;
+import java.util.*;
+
+/**
+ * This class implements
+ * <code>TcManager</code>, delegating the actual provision and creation of
+ * Graphs or MGraphs to registered
+ * <code>TcProvider</code>s. The class attempts to satisfy the request using the
+ * register
+ * <code>WeightedTcProvider</code> in decreasing order of weight. If multiple
+ * providers have the same weight the lexicographical order of the fully
+ * qualified class name determines which one is used, namely the one that occurs
+ * earlier. If a call to a registered provider causes an
+ * <code>IllegalArgumentException</code>,
+ * <code>NoSuchEntityException</code> or
+ * <code>UnsupportedOperationException</code> then the call is delegated to the
+ * next provider.
+ *
+ * Only one instance of this class should exist in a system, the public no
+ * argument constructor is meant for initialization by dependency injection
+ * systems such as OSGi-DS. Applications should use the static
+ * <code>getInstance()</code> method if they aren't using a framework that
+ * injects them the instance.
+ *
+ * This class returns
+ * <code>Graph</code>s a subtype of
+ * <code>Graph</code> that allows read/write locks.
+ *
+ * This class also registers all Graphs as services with the property
+ * 'name' indicating there name.
+ *
+ * Security checks are done when a Graph is retrieved. The returned
+ * Graph will do no further security checks. Because of this it
+ * should not be passed to a context where different access control applies. If
+ * an Graph is retrieved without having write permission the returned graph
+ * will be read-only.
+ *
+ * If a Graphs needs to passed around across different security
+ * contexts the one retrieved from the OSGi service whiteboard should be used as
+ * this performs access control on every access.
+ *
+ * @author reto, mir, hasan
+ *
+ */
+//immedia is set to true as this should register the ImmutableGraph services (even if manager service is not required)
+@Component(service = TcManager.class, immediate = true,
+ property={
+ "graph.cache.enabled=true",
+ "Graph.services.enabled=true"})
+public class TcManager extends TcProviderMultiplexer implements GraphStore {
+
+ public final static String GENERAL_PURPOSE_TC = "general.purpose.tc";
+ public final static String Graph_SERVICES_ENABLED = "Graph.services.enabled";
+ public final static String MGRAPH_CACHE_ENABLED = "graph.cache.enabled";
+
+ private static volatile TcManager instance;
+ private TcAccessController tcAccessController = new TcAccessController() {
+
+ @Override
+ protected TcManager getTcManager() {
+ return TcManager.this;
+ }
+
+ };
+ private Map<IRI, ServiceRegistration> serviceRegistrations = Collections
+ .synchronizedMap(new HashMap<IRI, ServiceRegistration>());
+
+ protected QueryEngine queryEngine;
+ private boolean isActivated = false;
+ private boolean isTcServicesEnabled = true;
+
+ private ComponentContext componentContext;
+ protected SortedSet<WeightedTcProvider> tempProviderList = new TreeSet<WeightedTcProvider>(
+ new WeightedProviderComparator());
+
+ /**
+ * the constructor sets the singleton instance to allow instantiation by
+ * OSGi-DS. This constructor should not be called except by OSGi-DS,
+ * otherwise the static
+ * <code>getInstance</code> method should be used.
+ */
+ public TcManager() {
+ TcManager.instance = this;
+ }
+
+ /**
+ * This returns the singleton instance. If an instance has been previously
+ * created (e.g. by OSGi declarative services) this instance is returned,
+ * otherwise a new instance is created and providers are injected using the
+ * service provider interface (META-INF/services/)
+ *
+ * @return the singleton instance
+ */
+ public static TcManager getInstance() {
+ if (instance == null) {
+ synchronized (TcManager.class) {
+ if (instance == null) {
+ instance = new TcManager();
+ instance.isActivated = true;
+ Iterator<WeightedTcProvider> weightedProviders = ServiceLoader
+ .load(WeightedTcProvider.class).iterator();
+ while (weightedProviders.hasNext()) {
+ WeightedTcProvider weightedProvider = weightedProviders
+ .next();
+ instance
+ .bindWeightedTcProvider(weightedProvider);
+ }
+ Iterator<QueryEngine> queryEngines = ServiceLoader.load(
+ QueryEngine.class).iterator();
+ System.out.println("looking for QE");
+ if (queryEngines.hasNext()) {
+ instance.queryEngine = queryEngines.next();
+ System.out.println("QE: "
+ + instance.queryEngine.getClass());
+ }
+ }
+ }
+ }
+ return instance;
+ }
+
+ protected void activate(final ComponentContext componentContext) {
+ this.componentContext = componentContext;
+
+ // Read configuration
+ isTcServicesEnabled = true;
+ Object configTcServicesEnabled = componentContext.getProperties().get(Graph_SERVICES_ENABLED);
+ if ( configTcServicesEnabled != null && configTcServicesEnabled instanceof String ) {
+ isTcServicesEnabled = Boolean.valueOf((String)configTcServicesEnabled);
+ }
+ Object configCacheEnabled = componentContext.getProperties().get(MGRAPH_CACHE_ENABLED);
+ if ( configCacheEnabled != null && configCacheEnabled instanceof String ) {
+ setCachingEnabled(Boolean.valueOf((String)configCacheEnabled));
+ }
+ isActivated = true;
+
+ for (WeightedTcProvider provider : tempProviderList) {
+ addWeightedTcProvider(provider);
+ }
+ tempProviderList.clear();
+ }
+
+ protected void deactivate(final ComponentContext componentContext) {
+ for (ServiceRegistration registration : serviceRegistrations.values()) {
+ registration.unregister();
+ }
+ serviceRegistrations.clear();
+ this.componentContext = null;
+ isActivated = false;
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ tcAccessController.checkReadPermission(name);
+ return super.getImmutableGraph(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) {
+ try {
+ tcAccessController.checkReadWritePermission(name);
+ } catch (AccessControlException e) {
+ tcAccessController.checkReadPermission(name);
+ return new WriteBlockedGraph(super.getMGraph(name));
+ }
+ return super.getMGraph(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name) {
+ try {
+ tcAccessController.checkReadWritePermission(name);
+ } catch (AccessControlException e) {
+ tcAccessController.checkReadPermission(name);
+ return new WriteBlockedGraph(
+ super.getGraph(name));
+ }
+ return super.getGraph(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name)
+ throws UnsupportedOperationException {
+ tcAccessController.checkReadWritePermission(name);
+ return super.createGraph(name);
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ tcAccessController.checkReadWritePermission(name);
+ return super.createImmutableGraph(name, triples);
+ }
+
+ @Override
+ public void deleteGraph(IRI name) {
+ tcAccessController.checkReadWritePermission(name);
+ super.deleteGraph(name);
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ return super.getNames(ImmutableGraph);
+ }
+
+ @Override
+ public Set<IRI> listNamedGraphs() {
+ return this.listGraphs();
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ Set<IRI> result = super.listGraphs();
+ return excludeNonReadable(result);
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ Set<IRI> result = super.listMGraphs();
+ return excludeNonReadable(result);
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ Set<IRI> result = super.listImmutableGraphs();
+ return excludeNonReadable(result);
+ }
+
+ private Set<IRI> excludeNonReadable(Set<IRI> tcNames) {
+ SecurityManager security = System.getSecurityManager();
+ if (security == null) {
+ return tcNames;
+ }
+ Set<IRI> result = new HashSet<IRI>();
+ for (IRI name : tcNames) {
+ try {
+ tcAccessController.checkReadPermission(name);
+ } catch (AccessControlException e) {
+ continue;
+ }
+ result.add(name);
+ }
+ return result;
+ }
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query. If the defaultGraph is available
+ * in this TcManages executeSparqlQuery(String, UriRef) should be used instead.
+ *
+ * @param query the sparql query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if no FROM clause is present
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ */
+ public Object executeSparqlQuery(String query, Graph defaultGraph) throws ParseException {
+ TcProvider singleTargetTcProvider = null;
+
+ final IRI defaultGraphName = new IRI("urn:x-temp:/kjsfadfhfasdffds");
+ final SparqlPreParser sparqlPreParser = new SparqlPreParser(this);
+ final Set<IRI> referencedGraphs = sparqlPreParser.getReferredGraphs(query, defaultGraphName);
+ if ((referencedGraphs != null) && (!referencedGraphs.contains(defaultGraphName))) {
+ singleTargetTcProvider = getSingleTargetTcProvider(referencedGraphs);
+ }
+ if ((singleTargetTcProvider != null) && (singleTargetTcProvider instanceof QueryableTcProvider)) {
+ return ((QueryableTcProvider) singleTargetTcProvider).executeSparqlQuery(query, null);
+ }
+ final QueryEngine queryEngine = this.queryEngine;
+ if (queryEngine != null) {
+ return queryEngine.execute(this, defaultGraph, query);
+ } else {
+ throw new NoQueryEngineException();
+ }
+ }
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query. Note that this method only works for
+ * queries that do not need a default ImmutableGraph.
+ *
+ * @param query the sparql query to execute
+ * @param forceFastlane indicate whether to force fastlane usage.
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ */
+ public Object executeSparqlQuery(String query, boolean forceFastlane) throws ParseException {
+ TcProvider singleTargetTcProvider = null;
+ if (forceFastlane) {
+ singleTargetTcProvider = getSingleTargetTcProvider(Collections.EMPTY_SET);
+ } else {
+ final IRI defaultGraphName = new IRI("urn:x-temp:/kjsfadfhfasdffds");
+ SparqlPreParser sparqlPreParser = new SparqlPreParser(this);
+ final Set<IRI> referencedGraphs = sparqlPreParser.getReferredGraphs(query, defaultGraphName);
+ if ((referencedGraphs != null) && (!referencedGraphs.contains(defaultGraphName))) {
+ singleTargetTcProvider = getSingleTargetTcProvider(referencedGraphs);
+ }
+ }
+
+ if ((singleTargetTcProvider != null) && (singleTargetTcProvider instanceof QueryableTcProvider)) {
+ return ((QueryableTcProvider)singleTargetTcProvider).executeSparqlQuery(query, null);
+ }
+ final QueryEngine queryEngine = this.queryEngine;
+ if (queryEngine != null) {
+ return queryEngine.execute(this, new SimpleGraph(), query);
+ } else {
+ throw new NoQueryEngineException();
+ }
+ }
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query. If the defaultGraph is available
+ * in this TcManages executeSparqlQuery(String, UriRef) should be used instead.
+ *
+ * @param query the sparql query to execute
+ * @param defaultGraphName the ImmutableGraph to be used as default ImmutableGraph in the Sparql ImmutableGraph Store
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ */
+ public Object executeSparqlQuery(String query, IRI defaultGraphName) throws ParseException {
+ return executeSparqlQuery(query, defaultGraphName, false);
+ }
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query. If the defaultGraph is available
+ * in this TcManages executeSparqlQuery(String, UriRef) should be used instead.
+ *
+ * @param query the sparql query to execute
+ * @param defaultGraph the ImmutableGraph to be used as default ImmutableGraph in the Sparql ImmutableGraph Store
+ * @param forceFastlane indicate whether to force fastlane usage.
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ */
+ public Object executeSparqlQuery(String query, IRI defaultGraphName, boolean forceFastlane) throws ParseException {
+ TcProvider singleTargetTcProvider = null;
+ if (forceFastlane) {
+ singleTargetTcProvider = getSingleTargetTcProvider(Collections.singleton(defaultGraphName));
+ } else {
+ SparqlPreParser sparqlPreParser = new SparqlPreParser(this);
+ final Set<IRI> referencedGraphs = sparqlPreParser.getReferredGraphs(query, defaultGraphName);
+ if ((referencedGraphs != null)) {
+ singleTargetTcProvider = getSingleTargetTcProvider(referencedGraphs);
+ }
+ }
+ if ((singleTargetTcProvider != null) && (singleTargetTcProvider instanceof QueryableTcProvider)) {
+ return ((QueryableTcProvider)singleTargetTcProvider).executeSparqlQuery(query, defaultGraphName);
+ }
+ final QueryEngine queryEngine = this.queryEngine;
+ if (queryEngine != null) {
+ return queryEngine.execute(this, this.getGraph(defaultGraphName), query);
+ } else {
+ throw new NoQueryEngineException();
+ }
+ }
+
+ /**
+ * Executes any sparql query. The type of the result object will vary
+ * depending on the type of the query.
+ *
+ * @param query the sparql query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if no FROM clause is present
+ * @return the resulting ResultSet, ImmutableGraph or Boolean value
+ *
+ * @deprecated Query is discontinued
+ */
+ @Deprecated
+ public Object executeSparqlQuery(Query query, Graph defaultGraph) {
+ final QueryEngine queryEngine = this.queryEngine;
+ if (queryEngine != null) {
+ return queryEngine.execute(this, defaultGraph, query.toString());
+ } else {
+ throw new NoQueryEngineException();
+ }
+ }
+
+ /**
+ * Executes a sparql SELECT query.
+ *
+ * @param query the sparql SELECT query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if not FROM clause is present
+ * @return the resulting ResultSet
+ * @deprecated Query is discontinued
+ */
+ @Deprecated
+ public ResultSet executeSparqlQuery(SelectQuery query,
+ Graph defaultGraph) {
+ return (ResultSet) executeSparqlQuery((Query) query, defaultGraph);
+ }
+
+ /**
+ * Executes a sparql ASK query.
+ *
+ * @param query the sparql ASK query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if not FROM clause is present
+ * @return the boolean value this query evaluates to
+ * @deprecated Query is discontinued
+ */
+ @Deprecated
+ public boolean executeSparqlQuery(AskQuery query,
+ Graph defaultGraph) {
+ return (Boolean) executeSparqlQuery((Query) query, defaultGraph);
+ }
+
+ /**
+ * Executes a sparql DESCRIBE query.
+ *
+ * @param query the sparql DESCRIBE query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if not FROM clause is present
+ * @return the resulting ImmutableGraph
+ * @deprecated Query is discontinued
+ */
+ @Deprecated
+ public ImmutableGraph executeSparqlQuery(DescribeQuery query,
+ Graph defaultGraph) {
+ return (ImmutableGraph) executeSparqlQuery((Query) query, defaultGraph);
+ }
+
+ /**
+ * Executes a sparql CONSTRUCT query.
+ *
+ * @param query the sparql CONSTRUCT query to execute
+ * @param defaultGraph the default ImmutableGraph against which to execute the query
+ * if not FROM clause is present
+ * @return the resulting ImmutableGraph
+ * @deprecated Query is discontinued
+ */
+ @Deprecated
+ public ImmutableGraph executeSparqlQuery(ConstructQuery query,
+ Graph defaultGraph) {
+ return (ImmutableGraph) executeSparqlQuery((Query) query, defaultGraph);
+ }
+
+ /**
+ * @return the TcAccessController that can be used to set the permissions
+ * needed to access a Triple Collection
+ */
+ public TcAccessController getTcAccessController() {
+ return tcAccessController;
+ }
+
+ /**
+ * Registers a provider
+ *
+ * @param provider the provider to be registered
+ */
+ @Reference(policy = ReferencePolicy.DYNAMIC,
+ cardinality = ReferenceCardinality.MULTIPLE)
+ protected void bindWeightedTcProvider(WeightedTcProvider provider) {
+ if (isActivated) {
+ addWeightedTcProvider(provider);
+ } else {
+ tempProviderList.add(provider);
+ }
+ }
+
+ /**
+ * Unregister a provider
+ *
+ * @param provider the provider to be deregistered
+ */
+ protected void unbindWeightedTcProvider(
+ WeightedTcProvider provider) {
+ removeWeightedTcProvider(provider);
+ }
+
+ /**
+ * Registers a provider
+ *
+ * @param provider the provider to be registered
+ */
+ @Reference(policy = ReferencePolicy.DYNAMIC,
+ cardinality = ReferenceCardinality.AT_LEAST_ONE,
+ target = "("+ TcManager.GENERAL_PURPOSE_TC+"=true)")
+ protected void bindGpWeightedTcProvider(WeightedTcProvider provider) {
+ if (isActivated) {
+ addWeightedTcProvider(provider);
+ } else {
+ tempProviderList.add(provider);
+ }
+ }
+
+ /**
+ * Unregister a provider
+ *
+ * @param provider the provider to be deregistered
+ */
+ protected void unbindGpWeightedTcProvider(
+ WeightedTcProvider provider) {
+ removeWeightedTcProvider(provider);
+ }
+
+ @Reference(policy = ReferencePolicy.DYNAMIC,
+ cardinality = ReferenceCardinality.OPTIONAL)
+ protected void bindQueryEngine(QueryEngine queryEngine) {
+ this.queryEngine = queryEngine;
+ }
+
+ protected void unbindQueryEngine(QueryEngine queryEngine) {
+ this.queryEngine = null;
+ }
+
+ @Override
+ protected void mGraphAppears(IRI name) {
+ if (isTcServicesEnabled()) {
+ // Only create the service when activated. When not activated
+ // creating will be delayed till after activation.
+ if (componentContext != null) {
+ registerGraphAsService(name, true);
+ }
+ }
+ }
+
+ @Override
+ protected void graphAppears(IRI name) {
+ if (isTcServicesEnabled()) {
+ // Only create the service when activated. When not activated
+ // creating will be delayed till after activation.
+ if (componentContext != null) {
+ registerGraphAsService(name, false);
+ }
+ }
+ }
+
+ private void registerGraphAsService(IRI name, boolean isMGraph) {
+ Dictionary<String,Object> props = new Hashtable<String, Object>();
+ props.put("name", name.getUnicodeString());
+ String[] interfaceNames;
+ Object service;
+ if (isMGraph) {
+ interfaceNames = new String[]{
+ Graph.class.getName(),
+ Graph.class.getName()
+ };
+ service = new MGraphServiceFactory(this, name, tcAccessController);
+ } else {
+ interfaceNames = new String[]{ImmutableGraph.class.getName()};
+ service = new ImmutableGraphServiceFactory(this, name, tcAccessController);
+ }
+ final int bundleState = componentContext.getBundleContext().getBundle().getState();
+ if ((bundleState == Bundle.ACTIVE) || (bundleState == Bundle.STARTING)) {
+ ServiceRegistration serviceReg = componentContext.getBundleContext()
+ .registerService(interfaceNames, service, props);
+ serviceRegistrations.put(name, serviceReg);
+ }
+ }
+
+ @Override
+ protected void tcDisappears(IRI name) {
+ ServiceRegistration reg = serviceRegistrations.get(name);
+ if (reg != null) {
+ reg.unregister();
+ serviceRegistrations.remove(name);
+ }
+ }
+
+ private TcProvider getSingleTargetTcProvider(final Set<IRI> referencedGraphs) {
+ TcProvider singleTargetTcProvider = null;
+ for (WeightedTcProvider provider : providerList) {
+ final Set<IRI> providerGraphs = provider.listGraphs();
+ if (providerGraphs.containsAll(referencedGraphs)) {
+ singleTargetTcProvider = provider;
+ break; //success
+ }
+ for (IRI graphName : referencedGraphs) {
+ if (providerGraphs.contains(graphName)) {
+ break; //failure
+ }
+ }
+ }
+ return singleTargetTcProvider;
+ }
+
+ public boolean isTcServicesEnabled() {
+ return isTcServicesEnabled;
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/TcProvider.java b/dataset/src/main/java/org/apache/clerezza/dataset/TcProvider.java
new file mode 100644
index 0000000..6135790
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/TcProvider.java
@@ -0,0 +1,151 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+
+import java.util.Set;
+
+/**
+ * A TC (Graph) Provider allows access to and optionally
+ * creation of named {@link ImmutableGraph}s and {@link Graph}s (mutable graphs)
+ *
+ * @author reto
+ */
+public interface TcProvider {
+
+ /**
+ * Get a <code>ImmutableGraph</code> by its name
+ *
+ * @param name the name of the ImmutableGraph
+ * @return the <code>ImmutableGraph</code> with the specified name
+ * @throws NoSuchEntityException if there is no <code>ImmutableGraph</code>
+ * with the specified name
+ */
+ ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException;
+
+ /**
+ * Get an <code>Graph</code> taht is not <code>ImmutableGrah</code>. The instances
+ * returned in different invocations are <code>equals</code>.
+ *
+ * @param the name of the <code>Graph</code>
+ * @return name the <code>Graph</code> with the specified name
+ * @throws NoSuchEntityException if there is no <code>Graph</code>
+ * with the specified name
+ */
+ Graph getMGraph(IRI name) throws NoSuchEntityException;
+
+ /**
+ * This method is used to get a <code>Graph</code> indifferently
+ * whether it's a ImmutableGraph or not. If the <code>name</code> names an
+ * <code>Graph</code> the result is the same as when invoking
+ * <code>getMGraph</code> with that argument, analogously for
+ * <code>ImmutableGraph</code>S the method returns an instance equals to what
+ * <code>getImmutableGraph</code> would return.
+ *
+ * @param name the name of the <Code>ImmutableGraph</code> or <code>Graph</code>
+ * @return the <Code>ImmutableGraph</code> or <code>Graph</code>
+ * @throws NoSuchEntityException if there is no <code>ImmutableGraph</code>
+ * or <code>Graph</code> with the specified name
+ */
+ Graph getGraph(IRI name) throws NoSuchEntityException;
+
+ /**
+ * Lists the name of the <Code>ImmutableGraph</code>s available through this
+ * <code>TcProvider</code>, implementations may take into account the
+ * security context and omit <Code>ImmutableGraph</code>s for which access is not
+ * allowed.
+ *
+ * @return the list of <Code>ImmutableGraph</code>s
+ */
+ Set<IRI> listImmutableGraphs();
+
+ /**
+ * Lists the name of the <Code>Graph</code>s available through this
+ * <code>TcProvider</code> that are not <Code>ImmutableGraph</code>, implementations may take into account the
+ * security context and omit <Code>Graph</code>s for which access is not
+ * allowed.
+ *
+ * @return the list of <Code>Graph</code>s
+ */
+ Set<IRI> listMGraphs();
+
+ /**
+ * Lists the name of the <Code>Graph</code>s available through this
+ * <code>TcProvider</code> indifferently whether they are mutables or
+ * immutables, implementations may take into account the security context and
+ * omit <Code>Graph</code>s for which access is not allowed.
+ *
+ * @return the list of <Code>Graph</code>s
+ */
+ Set<IRI> listGraphs();
+
+ /**
+ * Creates an initially empty <code>Graph</code> with a specified name
+ *
+ * @param name names the new <code>Graph</code>
+ * @return the newly created <code>Graph</code>
+ * @throws UnsupportedOperationException if this provider doesn't support
+ * creating <code>Graph</code>S
+ * @throws EntityAlreadyExistsException if an Graph with the specified name
+ * already exists
+ */
+ Graph createGraph(IRI name) throws UnsupportedOperationException,
+ EntityAlreadyExistsException;
+
+ /**
+ * Creates a <code>ImmutableGraph</code> with a specified name
+ *
+ * @param name the name of the <code>ImmutableGraph</code> to be created
+ * @param triples the triples of the new <code>ImmutableGraph</code>
+ * @return the newly created <code>ImmutableGraph</code>
+ * @throws UnsupportedOperationException if this provider doesn't support
+ * creating <code>ImmutableGraph</code>S
+ * @throws EntityAlreadyExistsException if a ImmutableGraph with the specified name
+ * already exists
+ */
+ ImmutableGraph createImmutableGraph(IRI name, Graph triples)
+ throws UnsupportedOperationException, EntityAlreadyExistsException;
+
+ /**
+ * Deletes the <code>ImmutableGraph</code> or <code>Graph</code> of a specified name.
+ * If <code>name</code> references a ImmutableGraph and the ImmutableGraph has other names, it
+ * will still be available with those other names.
+ *
+ * @param name the entity to be removed
+ * @throws UnsupportedOperationException if this provider doesn't support
+ * entities deletion.
+ * @throws NoSuchEntityException if <code>name</code> doesn't refer to a
+ * <code>ImmutableGraph</code> or an <code>Graph</code>.
+ * @throws EntityUndeletableException if the specified ImmutableGraph is undeletable
+ */
+ void deleteGraph(IRI name) throws UnsupportedOperationException,
+ NoSuchEntityException, EntityUndeletableException;
+
+ /**
+ * get a set of the names of a <code>ImmutableGraph</code>
+ *
+ * @param ImmutableGraph
+ * @return the set names of <code>ImmutableGraph</code>, the set is empty if
+ * <code>ImmutableGraph</code> is unknown
+ */
+ Set<IRI> getNames(ImmutableGraph immutableGraph);
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/TcProviderMultiplexer.java b/dataset/src/main/java/org/apache/clerezza/dataset/TcProviderMultiplexer.java
new file mode 100644
index 0000000..ceaddc3
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/TcProviderMultiplexer.java
@@ -0,0 +1,446 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+
+/**
+ * This makes a set of WeightedTcProvider appear as one TcProvider. It delegates
+ * requests to the WeightedTcProvider with the highest Weight
+ *
+ * @author reto
+ */
+public class TcProviderMultiplexer implements TcProvider {
+
+ protected SortedSet<WeightedTcProvider> providerList = new TreeSet<>(
+ new WeightedProviderComparator());
+ /**
+ * Mapping to Graph's and ServiceRegistration using their URI's as key.
+ * Makes sure that per URI only one instance of the Graph is used,
+ * otherwise the locks in the <code>Graph</code>s would have no effect
+ * between different instances and concurrency issues could occur.
+ */
+ private Map<IRI, MGraphHolder> mGraphCache = Collections.synchronizedMap(new HashMap<IRI, MGraphHolder>());
+
+ /**
+ * Flag to indicate whether mgraphs should be cached for faster access. By
+ * default caching is enabled for backward compatibility.
+ */
+ private boolean isCachingEnabled = true;
+
+ /**
+ * Registers a provider
+ *
+ * @param provider
+ * the provider to be registered
+ */
+ public void addWeightedTcProvider(WeightedTcProvider provider) {
+ providerList.add(provider);
+ updateGraphCache(provider, true);
+ }
+
+ /**
+ * Unregister a provider
+ *
+ * @param provider
+ * the provider to be deregistered
+ */
+ public void removeWeightedTcProvider(
+ WeightedTcProvider provider) {
+ providerList.remove(provider);
+ updateGraphCache(provider, false);
+ }
+
+ /**
+ * subclasses overwrite this method to be notified when a new
+ * ImmutableGraph is available (either because it has been created or being
+ * provided by a newly added WeightedTcProvider). The default implementation
+ * does nothing.
+ *
+ * @param name
+ */
+ protected void graphAppears(IRI name) {
+ }
+
+ /**
+ * subclasses overwrite this method to be notified when a new
+ * Graph is available (either because it has been created or being
+ * provided by a newly added WeightedTcProvider). The default implementation
+ * does nothing.
+ *
+ * @param name
+ */
+ protected void mGraphAppears(IRI name) {
+ }
+
+ /**
+ * subclasses overwrite this method to be notified whenGraph is
+ * no longer available (either because it has been deleted or bacause its
+ * WeightedTcProvider was removed). The default implementation does nothing.
+ *
+ * for implementational reasons even for name of Graph not
+ * previously registered.
+ *
+ * @param name
+ */
+ protected void tcDisappears(IRI name) {
+ }
+
+ /**
+ * Updates the lockableMGraphCache AFTER a new <code>provider</code> was
+ * bound or unbound.
+ * This method also takes care of registering and unregistering
+ * provided triple collections as services based on the weight of
+ * all affected providers.
+ *
+ * @param provider
+ * the provider that was added or removed
+ * @param providerAdded
+ * <code>boolean</code> that should be set as <code>true</code>
+ * if <code>provider</code> was added to
+ * <code>org.apache.clerezza.rdf.core.TcManager.providerList</code>
+ * otherwise <code>false</code>
+ */
+ private void updateGraphCache(WeightedTcProvider provider,
+ boolean providerAdded) {
+ Set<IRI> uriSet = provider.listGraphs();
+ if (!(uriSet == null || uriSet.isEmpty())) {
+ if (providerAdded) {
+ weightedProviderAdded(provider, uriSet);
+ } else {
+ weightedProviderRemoved(provider, uriSet);
+ }
+ }
+ }
+
+ private void weightedProviderAdded(WeightedTcProvider newProvider,
+ Set<IRI> newProvidedUris) {
+ Set<WeightedTcProvider> lowerWeightedProviderList = getLowerWeightedProvider(newProvider);
+ if (isCachingEnabled()) {
+ for (IRI name : newProvidedUris) {
+ final MGraphHolder holder = mGraphCache.get(name);
+ if ((holder != null) && (holder.getWeightedTcProvider() != null)) {
+ if (lowerWeightedProviderList.contains(holder.getWeightedTcProvider())) {
+ tcDisappears(name);
+ mGraphCache.remove(name);
+ } else {
+ continue;
+ }
+ }
+ Graph triples = newProvider.getGraph(name);
+ if (triples instanceof Graph) {
+ mGraphCache.put(name, new MGraphHolder(newProvider, ensureLockable((Graph)triples)));
+ mGraphAppears(name);
+ } else {
+ graphAppears(name);
+ }
+ }
+ }
+ }
+
+
+
+ private Set<WeightedTcProvider> getLowerWeightedProvider(
+ WeightedTcProvider newProvider) {
+ boolean referenceProviderPassed = false;
+ Set<WeightedTcProvider> lowerWeightedProviderList = new HashSet<WeightedTcProvider>();
+ for (WeightedTcProvider weightedProvider : providerList) {
+ if (referenceProviderPassed) {
+ lowerWeightedProviderList.add(weightedProvider);
+ } else if (newProvider.equals(weightedProvider)) {
+ referenceProviderPassed = true;
+ }
+ }
+ return lowerWeightedProviderList;
+ }
+
+ private void weightedProviderRemoved(WeightedTcProvider oldProvider,
+ Set<IRI> oldProvidedUris) {
+ for (IRI name : oldProvidedUris) {
+ final MGraphHolder holder = mGraphCache.get(name);
+ if ((holder != null) && (holder.getWeightedTcProvider() != null)
+ && holder.getWeightedTcProvider().equals(oldProvider)) {
+ tcDisappears(name);
+ mGraphCache.remove(name);
+
+ if (isCachingEnabled()) {
+ // check if another WeightedTcProvider has the Graph.
+ // And if so register as service.
+ for (WeightedTcProvider provider : providerList) {
+ try {
+ Graph triples = provider.getGraph(name);
+ if (triples instanceof Graph) {
+ mGraphCache.put(name, new MGraphHolder(provider, ensureLockable((Graph)triples)));
+ mGraphAppears(name);
+ } else {
+ graphAppears(name);
+ }
+ break;
+ } catch (NoSuchEntityException e) {
+ // continue;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ for (TcProvider provider : providerList) {
+ try {
+ return provider.getImmutableGraph(name);
+ } catch (NoSuchEntityException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name)
+ throws NoSuchEntityException {
+ Graph result = getMGraphFromCache(name);
+ if (result == null) {
+ synchronized (this) {
+ result = getMGraphFromCache(name);
+ if (result == null) {
+ result = getUnsecuredMGraphAndAddToCache(name);
+ }
+ }
+ }
+ return result;
+ }
+
+ private Graph getMGraphFromCache(IRI name) {
+ MGraphHolder holder = mGraphCache.get(name);
+ if (holder == null) {
+ return null;
+ }
+ return holder.getMGraph();
+ }
+
+ private Graph getUnsecuredMGraphAndAddToCache(IRI name)
+ throws NoSuchEntityException {
+ for (WeightedTcProvider provider : providerList) {
+ try {
+ Graph providedMGraph = provider.getMGraph(name);
+ Graph result = ensureLockable(providedMGraph);
+
+ if (isCachingEnabled()) {
+ mGraphCache.put(name, new MGraphHolder(
+ provider, result));
+ }
+ return result;
+ } catch (NoSuchEntityException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name)
+ throws NoSuchEntityException {
+ Graph result;
+ for (WeightedTcProvider provider : providerList) {
+ try {
+ result = provider.getGraph(name);
+ if (result instanceof ImmutableGraph) {
+ return result;
+ } else {
+ // This is to ensure the Graph gets added to the cache
+ return getMGraph(name);
+ }
+ } catch (NoSuchEntityException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name)
+ throws UnsupportedOperationException {
+
+ for (WeightedTcProvider provider : providerList) {
+ try {
+ Graph result = provider.createGraph(name);
+ // unregisters a possible ImmutableGraph or Graph service under this name
+ // provided by a WeightedTcProvider with a lower weight.
+ tcDisappears(name);
+ if (isCachingEnabled()) {
+ mGraphCache.put(name, new MGraphHolder(provider, null));
+ }
+ mGraphAppears(name);
+ return result;
+ } catch (UnsupportedOperationException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ throw new UnsupportedOperationException(
+ "No provider could create Graph.");
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ for (WeightedTcProvider provider : providerList) {
+ try {
+ ImmutableGraph result = provider.createImmutableGraph(name, triples);
+
+ // unregisters a possible ImmutableGraph or Graph service under this name
+ // provided by a WeightedTcProvider with a lower weight.
+ tcDisappears(name);
+ if (isCachingEnabled()) {
+ mGraphCache.put(name, new MGraphHolder(provider, null));
+ }
+ graphAppears(name);
+ return result;
+ } catch (UnsupportedOperationException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ throw new UnsupportedOperationException(
+ "No provider could create ImmutableGraph.");
+ }
+
+ @Override
+ public void deleteGraph(IRI name) {
+ for (TcProvider provider : providerList) {
+ try {
+ provider.deleteGraph(name);
+ final MGraphHolder holder = mGraphCache.get(name);
+ if ((holder != null)
+ && (holder.getWeightedTcProvider() != null)
+ && holder.getWeightedTcProvider().equals(provider)) {
+ tcDisappears(name);
+ mGraphCache.remove(name);
+ }
+ return;
+ } catch (UnsupportedOperationException e) {
+ // we do nothing and try our luck with the next provider
+ } catch (NoSuchEntityException e) {
+ //we do nothing and try our luck with the next provider
+ } catch (IllegalArgumentException e) {
+ //we do nothing and try our luck with the next provider
+ }
+ }
+ // this throws a NoSuchEntityException if the ImmutableGraph doesn't exist
+ getGraph(name);
+ // the entity exists but cannot be deleted
+ throw new UnsupportedOperationException(
+ "No provider could delete the entity.");
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ Set<IRI> result = new HashSet<IRI>();
+ for (TcProvider provider : providerList) {
+ result.addAll(provider.getNames(ImmutableGraph));
+ }
+ return result;
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ Set<IRI> result = new HashSet<IRI>();
+ for (TcProvider provider : providerList) {
+ result.addAll(provider.listGraphs());
+ }
+ return result;
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ Set<IRI> result = new HashSet<IRI>();
+ for (TcProvider provider : providerList) {
+ result.addAll(provider.listMGraphs());
+ }
+ return result;
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ Set<IRI> result = new HashSet<IRI>();
+ for (TcProvider provider : providerList) {
+ result.addAll(provider.listImmutableGraphs());
+ }
+ return result;
+ }
+
+ private Graph ensureLockable(Graph providedMGraph) {
+ //Graphs are alway locable now
+ return providedMGraph;
+ }
+
+ /**
+ * Contains an unsecured Graph, a ServiceRegistration and
+ * the WeightedTcProvider that generated the ImmutableGraph
+ */
+ private static class MGraphHolder {
+
+ private WeightedTcProvider tcProvider;
+ private WeakReference<Graph> mGraphReference;
+
+ MGraphHolder(WeightedTcProvider tcProvider, Graph graph) {
+ this.tcProvider = tcProvider;
+ this.mGraphReference = new WeakReference<Graph>(graph);
+ }
+
+ Graph getMGraph() {
+ return this.mGraphReference.get();
+ }
+
+ WeightedTcProvider getWeightedTcProvider() {
+ return this.tcProvider;
+ }
+ }
+
+ //methods for debuging / monitoring
+ public SortedSet<WeightedTcProvider> getProviderList() {
+ return providerList;
+ }
+
+ public boolean isCachingEnabled() {
+ return isCachingEnabled;
+ }
+
+ public void setCachingEnabled(boolean isCachingEnabled) {
+ this.isCachingEnabled = isCachingEnabled;
+
+ if (!isCachingEnabled()) {
+ mGraphCache.clear();
+ }
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/WeightedProviderComparator.java b/dataset/src/main/java/org/apache/clerezza/dataset/WeightedProviderComparator.java
new file mode 100644
index 0000000..66752f3
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/WeightedProviderComparator.java
@@ -0,0 +1,41 @@
+package org.apache.clerezza.dataset;
+/*
+ *
+ * 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.
+ *
+*/
+
+
+import java.util.Comparator;
+
+/**
+ * Compares the WeightedTcManagementProviders, descending for weight and
+ * ascending by name
+ */
+public class WeightedProviderComparator implements Comparator<WeightedTcProvider> {
+
+ @Override
+ public int compare(WeightedTcProvider o1, WeightedTcProvider o2) {
+ int o1Weight = o1.getWeight();
+ int o2Weight = o2.getWeight();
+ if (o1Weight != o2Weight) {
+ return o2Weight - o1Weight;
+ }
+ return o1.getClass().toString().compareTo(o2.getClass().toString());
+ }
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/WeightedTcProvider.java b/dataset/src/main/java/org/apache/clerezza/dataset/WeightedTcProvider.java
new file mode 100644
index 0000000..e50514d
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/WeightedTcProvider.java
@@ -0,0 +1,36 @@
+/*
+ * 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.dataset;
+
+/**
+ * This interface is implemented by providers to which {@link TcManagerImpl}
+ * delegates.
+ *
+ * @author reto
+ */
+public interface WeightedTcProvider extends TcProvider {
+
+ /**
+ * Get the weight of this provider. {@link TcManager} will prioritize
+ * <code>TcProvider</code>s with greater weight.
+ *
+ * @return a positive number indicating the weight of the provider
+ */
+ int getWeight();
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/package.html b/dataset/src/main/java/org/apache/clerezza/dataset/package.html
new file mode 100644
index 0000000..8d136ed
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/package.html
@@ -0,0 +1,56 @@
+
+ <!--
+/*
+ * 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.
+ */
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>org.apache.clerezza.dataset</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ <p>This package provides access to named {@link
+ org.apache.clerezza.api.ImmutableGraph}S and {@link
+ org.apache.clerezza.api.Graph}S that may originate from various
+ implementations.</p>
+ <h3>Accessing</h3>
+ <p>
+ If running in a dependency injection system you should get an instance
+ of
+ <code>TcManager</code>
+ by the framework, otherwise use the static method
+ <code>TcManager.getInstance</code>
+ .
+ </p>
+ <h3>Adding a provider</h3>
+ <p>A provider implements {@link WeightedTcProvider}.</p>
+ <p>
+ To work outside a component injection framework it contains a file
+ <code>META-INF/services/org.apache.clerezza.dataset.WeightedTcProvider</code>
+ containing the name of the implementing class.
+ </p>
+ <p>
+ To work in a OSGi-DS context the provider register a component
+ exposing
+ <code>org.apache.clerezza.dataset.WeightedTcProvider</code>
+ as service interface.
+ </p>
+ </body>
+</html>
\ No newline at end of file
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/security/TcAccessController.java b/dataset/src/main/java/org/apache/clerezza/dataset/security/TcAccessController.java
new file mode 100644
index 0000000..93b54ff
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/security/TcAccessController.java
@@ -0,0 +1,342 @@
+/*
+ * 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.dataset.security;
+
+import org.apache.clerezza.api.*;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.literal.LiteralFactory;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.TcManager;
+import org.apache.clerezza.utils.security.PermissionParser;
+
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.Permission;
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * Controls the permissions needed to access a triple collection provided by
+ * <code>TcManager</code>.
+ *
+ * Clients with a ConfigureTcAcessPermission can set the permissions required to
+ * access a Graph. These permissions are stored persistently in an
+ * Graph named urn:x-localinstance:/graph-access.graph
+ *
+ * Clients should get an instance from TcManager.getTcAccessController()
+ *
+ * @author reto
+ */
+public abstract class TcAccessController {
+
+ private final TcManager tcManager;
+ private final IRI permissionGraphName = new IRI("urn:x-localinstance:/graph-access.graph");
+ //we can't rely on ontology plugin in rdf core
+ private String ontologyNamespace = "http://clerezza.apache.org/2010/07/10/graphpermssions#";
+ private final IRI readPermissionListProperty = new IRI(ontologyNamespace + "readPermissionList");
+ private final IRI readWritePermissionListProperty = new IRI(ontologyNamespace + "readWritePermissionList");
+ /**
+ * The first item in the subject RDF list.
+ */
+ public static final IRI first = new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
+ /**
+ * The rest of the subject RDF list after the first item.
+ */
+ public static final IRI rest = new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
+ public static final IRI rdfNil = new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
+ private final Map<IRI, Collection<Permission>> readPermissionCache =
+ Collections.synchronizedMap(new HashMap<IRI, Collection<Permission>>());
+ private final Map<IRI, Collection<Permission>> readWritePermissionCache =
+ Collections.synchronizedMap(new HashMap<IRI, Collection<Permission>>());
+
+ /**
+ *
+ * @param tcManager the tcManager used to locate urn:x-localinstance:/graph-access.graph
+ */
+ public TcAccessController() {
+ this.tcManager = getTcManager();
+ }
+
+ public void checkReadPermission(IRI GraphUri) {
+ if (GraphUri.equals(permissionGraphName)) {
+ //This is world readable, as this prevents as from doingf things as
+ //priviledged during verfification
+ return;
+ }
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ //will AllPermissions the rest is obsolete
+ try {
+ AccessController.checkPermission(new AllPermission());
+ } catch (AccessControlException e) {
+ Collection<Permission> perms = getRequiredReadPermissions(GraphUri);
+ if (perms.size() > 0) {
+ for (Permission permission : perms) {
+ AccessController.checkPermission(permission);
+ }
+ } else {
+ AccessController.checkPermission(new TcPermission(
+ GraphUri.getUnicodeString(), TcPermission.READ));
+ }
+ }
+ }
+ }
+
+ public void checkReadWritePermission(IRI GraphUri) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ //will AllPermissions the rest is obsolete
+ try {
+ AccessController.checkPermission(new AllPermission());
+ } catch (AccessControlException e) {
+ if (GraphUri.equals(permissionGraphName)) {
+ AccessController.checkPermission(new TcPermission(
+ GraphUri.getUnicodeString(), TcPermission.READWRITE));
+ } else {
+ Collection<Permission> perms = getRequiredReadWritePermissions(GraphUri);
+ if (perms.size() > 0) {
+ for (Permission permission : perms) {
+ AccessController.checkPermission(permission);
+ }
+ } else {
+ AccessController.checkPermission(new TcPermission(
+ GraphUri.getUnicodeString(), TcPermission.READWRITE));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the set of permissions required for read access to a triple-collection, if
+ * the set is non-empty the default TCPermisson is no longer required.
+ *
+ * @param GraphUri
+ * @param permissionDescriptions
+ */
+ public void setRequiredReadPermissionStrings(IRI GraphUri,
+ Collection<String> permissionDescriptions) {
+ readPermissionCache.remove(GraphUri);
+ final Graph permissionMGraph = getOrCreatePermisionGraph();
+ Lock l = permissionMGraph.getLock().writeLock();
+ l.lock();
+ try {
+ removeExistingRequiredReadPermissions(GraphUri, permissionMGraph);
+ final BlankNodeOrIRI permissionList = createList(permissionDescriptions.iterator(), permissionMGraph);
+ permissionMGraph.add(new TripleImpl(GraphUri,
+ readPermissionListProperty, permissionList));
+ } finally {
+ l.unlock();
+ }
+ }
+
+ /**
+ * Set the set of permissions required for read access to a triple-collection, if
+ * the set is non-empty the default TCPermisson is no longer required.
+ *
+ * @param GraphUri
+ * @param permissionDescriptions
+ */
+ public void setRequiredReadPermissions(IRI GraphUri,
+ Collection<Permission> permissions) {
+ Collection<String> permissionStrings = new ArrayList<String>();
+ for (Permission permission : permissions) {
+ permissionStrings.add(permission.toString());
+ }
+ setRequiredReadPermissionStrings(GraphUri, permissionStrings);
+ }
+
+ /**
+ * Set the set of permissions required for read-write access to a
+ * triple-collection, if
+ * the set is non-empty the default TCPermisson is no longer required.
+ *
+ * @param GraphUri
+ * @param permissionDescriptions
+ */
+ public void setRequiredReadWritePermissionStrings(IRI GraphUri,
+ Collection<String> permissionDescriptions) {
+ readWritePermissionCache.remove(GraphUri);
+ final Graph permissionMGraph = getOrCreatePermisionGraph();
+ Lock l = permissionMGraph.getLock().writeLock();
+ l.lock();
+ try {
+ removeExistingRequiredReadPermissions(GraphUri, permissionMGraph);
+ final BlankNodeOrIRI permissionList = createList(permissionDescriptions.iterator(), permissionMGraph);
+ permissionMGraph.add(new TripleImpl(GraphUri,
+ readWritePermissionListProperty, permissionList));
+ } finally {
+ l.unlock();
+ }
+ }
+
+ /**
+ * Set the set of permissions required for read-write access to a
+ * triple-collection, if
+ * the set is non-empty the default TCPermisson is no longer required.
+ *
+ * @param GraphUri
+ * @param permissionDescriptions
+ */
+ public void setRequiredReadWritePermissions(IRI GraphUri,
+ Collection<Permission> permissions) {
+ Collection<String> permissionStrings = new ArrayList<String>();
+ for (Permission permission : permissions) {
+ permissionStrings.add(permission.toString());
+ }
+ setRequiredReadWritePermissionStrings(GraphUri, permissionStrings);
+ }
+
+ /**
+ * Get the set of permissions required for read access to the
+ * triple-collection, the set may be empty meaning that the default
+ * TCPermission is required.
+ *
+ * @param GraphUri
+ * @return the collection of permissions
+ */
+ public Collection<Permission> getRequiredReadPermissions(IRI GraphUri) {
+ Collection<Permission> result = readPermissionCache.get(GraphUri);
+ if (result == null) {
+ result = new ArrayList<Permission>();
+ Collection<String> permissionStrings = getRequiredReadPermissionStrings(GraphUri);
+ for (String string : permissionStrings) {
+ result.add(PermissionParser.getPermission(string, getClass().getClassLoader()));
+ }
+ readPermissionCache.put(GraphUri, result);
+ }
+ return result;
+ }
+
+ /**
+ * Get the set of permissions required for read-write access to the
+ * triple-collection, the set may be empty meaning that the default
+ * TCPermission is required.
+ *
+ * @param GraphUri
+ * @return the collection of permissions
+ */
+ public Collection<Permission> getRequiredReadWritePermissions(IRI GraphUri) {
+ Collection<Permission> result = readWritePermissionCache.get(GraphUri);
+ if (result == null) {
+ result = new ArrayList<Permission>();
+ Collection<String> permissionStrings = getRequiredReadWritePermissionStrings(GraphUri);
+ for (String string : permissionStrings) {
+ result.add(PermissionParser.getPermission(string, getClass().getClassLoader()));
+ }
+ readWritePermissionCache.put(GraphUri, result);
+ }
+ return result;
+ }
+
+ private BlankNodeOrIRI createList(Iterator<String> iterator, Graph permissionMGraph) {
+ if (!iterator.hasNext()) {
+ return rdfNil;
+ }
+ final BlankNode result = new BlankNode();
+ permissionMGraph.add(new TripleImpl(result, first,
+ LiteralFactory.getInstance().createTypedLiteral(iterator.next())));
+ permissionMGraph.add(new TripleImpl(result, rest,
+ createList(iterator, permissionMGraph)));
+ return result;
+
+ }
+
+ //called withiong write-lock
+ private void removeExistingRequiredReadPermissions(IRI GraphUri,
+ Graph permissionMGraph) {
+ try {
+ Triple t = permissionMGraph.filter(GraphUri, readPermissionListProperty, null).next();
+ RDFTerm list = t.getObject();
+ removeList((BlankNodeOrIRI) list, permissionMGraph);
+ permissionMGraph.remove(t);
+ } catch (NoSuchElementException e) {
+ //There was no existing to remove
+ }
+ }
+
+ private void removeList(BlankNodeOrIRI list, Graph permissionMGraph) {
+ try {
+ Triple t = permissionMGraph.filter(list, rest, null).next();
+ RDFTerm restList = t.getObject();
+ removeList((BlankNodeOrIRI) restList, permissionMGraph);
+ permissionMGraph.remove(t);
+ Iterator<Triple> iter = permissionMGraph.filter(list, first, null);
+ iter.next();
+ iter.remove();
+ } catch (NoSuchElementException e) {
+ //if it has no rest its rdf:NIL and has no first
+ }
+ }
+
+ private Collection<String> getRequiredReadWritePermissionStrings(final IRI GraphUri) {
+ return getRequiredPermissionStrings(GraphUri, readWritePermissionListProperty);
+ }
+ private Collection<String> getRequiredReadPermissionStrings(final IRI GraphUri) {
+ return getRequiredPermissionStrings(GraphUri, readPermissionListProperty);
+ }
+ private Collection<String> getRequiredPermissionStrings(final IRI GraphUri, IRI property) {
+ try {
+ final Graph permissionMGraph = tcManager.getMGraph(permissionGraphName);
+ Lock l = permissionMGraph.getLock().readLock();
+ l.lock();
+ try {
+ Triple t = permissionMGraph.filter(GraphUri, property, null).next();
+ BlankNodeOrIRI list = (BlankNodeOrIRI) t.getObject();
+ LinkedList<String> result = new LinkedList<String>();
+ readList(list, permissionMGraph, result);
+ return result;
+ } catch (NoSuchElementException e) {
+ return new ArrayList<String>(0);
+ } finally {
+ l.unlock();
+ }
+ } catch (NoSuchEntityException e) {
+ return new ArrayList<String>(0);
+ }
+ }
+
+ private void readList(BlankNodeOrIRI list, Graph permissionMGraph, LinkedList<String> target) {
+ if (list.equals(rdfNil)) {
+ return;
+ }
+ Triple restTriple = permissionMGraph.filter(list, rest, null).next();
+ BlankNodeOrIRI restList = (BlankNodeOrIRI) restTriple.getObject();
+ readList(restList, permissionMGraph, target);
+ Triple firstTriple = permissionMGraph.filter(list, first, null).next();
+ Literal firstValue = (Literal) firstTriple.getObject();
+ String value = LiteralFactory.getInstance().createObject(String.class, firstValue);
+ target.addFirst(value);
+ }
+
+ private Graph getOrCreatePermisionGraph() {
+ try {
+ return tcManager.getMGraph(permissionGraphName);
+ } catch (NoSuchEntityException e) {
+ return tcManager.createGraph(permissionGraphName);
+ }
+ }
+
+ /**
+ * Note that this will only be invoked once
+ * @return
+ */
+ protected abstract TcManager getTcManager();
+}
diff --git a/dataset/src/main/java/org/apache/clerezza/dataset/security/TcPermission.java b/dataset/src/main/java/org/apache/clerezza/dataset/security/TcPermission.java
new file mode 100644
index 0000000..c218dd9
--- /dev/null
+++ b/dataset/src/main/java/org/apache/clerezza/dataset/security/TcPermission.java
@@ -0,0 +1,149 @@
+/*
+ * 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.dataset.security;
+
+import java.security.Permission;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * A permission to access <code>Graph<code>s matching a specified
+ * name pattern. A pattern is matched if and only if the pattern is equals
+ * to name of the <code>Graph<code> or the pattern ends with "/*" and
+ * the name of the <code>Graph<code> starts with the characters
+ * preceding the '*' in the pattern.
+ *
+ * @author reto, tsuy
+ */
+public class TcPermission extends Permission {
+ public final static String READWRITE = "readwrite";
+ public final static String READ = "read";
+
+ private String tcNamePattern;
+ /**
+ * true if readwrite granted false if only read
+ */
+ private boolean allowReadWrite = false;
+
+ final static Pattern actionPattern = Pattern.compile(",( *)");
+ /**
+ * Conststructs a TcPermission for a specified name pattern and a list of
+ * actions.
+ *
+ * @param tcNamePattern see class description
+ * @param actions a comma separated list of the strings "read" and "readwrite",
+ * the canonical form is just "read" or "readwrite" as "readwrite"
+ * implies "read".
+ */
+ public TcPermission(String tcNamePattern, String actions) {
+ super(tcNamePattern);
+ this.tcNamePattern = tcNamePattern;
+ //check and set actions
+ final Set actionSet = new HashSet(Arrays.asList(actionPattern.split(actions)));
+ if (actionSet.remove(READWRITE)) {
+ allowReadWrite = true;
+ } else {
+ if (!actionSet.contains(READ)) {
+ throw new IllegalArgumentException("actions must be either \"read\" or \"readwrite\"");
+ }
+ }
+ actionSet.remove(READ);
+ if (actionSet.size() > 0) {
+ throw new IllegalArgumentException("actions must only contain \"read\" and \"readwrite\"");
+ }
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ if (permission instanceof TcPermission) {
+ TcPermission other = (TcPermission) permission;
+ if (!patternImplies(other.tcNamePattern)) {
+ return false;
+ }
+ if (!actionsImplies(other.allowReadWrite)) {
+ return false;
+ }
+ return true;
+
+
+ }
+ return false;
+ }
+
+ private boolean actionsImplies(boolean readwriteOther) {
+ if (!readwriteOther) {
+ return true;
+ } else {
+ return allowReadWrite;
+ }
+
+ }
+
+ private boolean patternImplies(String tcNamePatternOther) {
+ if (tcNamePattern.equals(tcNamePatternOther)) {
+ return true;
+ }
+ if (tcNamePattern.endsWith("/*")) {
+ return tcNamePatternOther.startsWith(
+ tcNamePattern.substring(0, tcNamePattern.length()-1));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TcPermission other = (TcPermission) obj;
+ if (this.tcNamePattern != other.tcNamePattern
+ && (this.tcNamePattern == null
+ || !this.tcNamePattern.equals(other.tcNamePattern))) {
+ return false;
+ }
+ if (this.allowReadWrite != other.allowReadWrite) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 97 * hash + (this.tcNamePattern != null ?
+ this.tcNamePattern.hashCode() : 0);
+ if (allowReadWrite) {
+ hash++;
+ }
+ return hash;
+ }
+
+
+
+ @Override
+ public String getActions() {
+ return allowReadWrite ? READWRITE : READ;
+ }
+
+}
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/SecurityTest.java b/dataset/src/test/java/org/apache/clerezza/dataset/SecurityTest.java
new file mode 100644
index 0000000..ffea930
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/SecurityTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.Triple;
+import org.apache.clerezza.api.impl.graph.ReadOnlyException;
+import org.apache.clerezza.api.impl.literal.PlainLiteralImpl;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.dataset.providers.WeightedA;
+import org.apache.clerezza.dataset.providers.WeightedDummy;
+import org.apache.clerezza.dataset.security.TcPermission;
+import org.junit.*;
+
+import java.io.FilePermission;
+import java.lang.reflect.ReflectPermission;
+import java.security.*;
+import java.util.Collections;
+import java.util.PropertyPermission;
+
+/**
+ *
+ * @author reto
+ */
+public class SecurityTest {
+
+ public SecurityTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ ////needed to unbind because this is injected with META-INF/services - file
+ TcManager.getInstance().unbindWeightedTcProvider(new WeightedA());
+ TcManager.getInstance().bindWeightedTcProvider(new WeightedDummy());
+ TcManager.getInstance().createGraph(new IRI("http://example.org/ImmutableGraph/alreadyexists"));
+ TcManager.getInstance().createGraph(new IRI("http://example.org/read/ImmutableGraph"));
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() {
+
+ Policy.setPolicy(new Policy() {
+
+ @Override
+ public PermissionCollection getPermissions(CodeSource codeSource) {
+ PermissionCollection result = new Permissions();
+ result.add(new TcPermission("http://example.org/permitted", "read"));
+ result.add(new TcPermission("http://example.org/ImmutableGraph/alreadyexists", "readwrite"));
+ result.add(new TcPermission("http://example.org/read/ImmutableGraph", "read"));
+ result.add(new TcPermission("http://example.org/area/allowed/*", "readwrite"));
+ result.add(new TcPermission("urn:x-localinstance:/graph-access.graph", "readwrite"));
+ //result.add(new AllPermission());
+ result.add(new RuntimePermission("*"));
+ result.add(new ReflectPermission("suppressAccessChecks"));
+ result.add(new PropertyPermission("*", "read"));
+ //(java.util.PropertyPermission line.separator read)
+ result.add(new FilePermission("/-", "read,write"));
+ return result;
+ }
+ });
+ System.setSecurityManager(new SecurityManager() {
+
+ @Override
+ public void checkPermission(Permission perm) {
+ //System.out.println("Checking "+perm);
+ super.checkPermission(perm);
+ }
+
+ @Override
+ public void checkPermission(Permission perm, Object context) {
+ //System.out.println("Checking "+perm);
+ super.checkPermission(perm, context);
+ }
+
+ });
+ }
+
+ @After
+ public void tearDown() {
+ System.setSecurityManager(null);
+ }
+
+
+ @Test(expected=NoSuchEntityException.class)
+ public void testAcessGraph() {
+ TcManager.getInstance().getImmutableGraph(new IRI("http://example.org/permitted"));
+ }
+
+ @Test(expected=AccessControlException.class)
+ public void testNoWildCard() {
+ TcManager.getInstance().getImmutableGraph(new IRI("http://example.org/permitted/subthing"));
+ }
+
+ @Test(expected=NoSuchEntityException.class)
+ public void testAllowedArea() {
+ TcManager.getInstance().getImmutableGraph(new IRI("http://example.org/area/allowed/something"));
+ }
+
+ @Test(expected=AccessControlException.class)
+ public void testAcessForbiddenGraph() {
+ TcManager.getInstance().getImmutableGraph(new IRI("http://example.org/forbidden"));
+ }
+
+ @Test(expected=NoSuchEntityException.class)
+ public void testCustomPermissions() {
+ IRI graphUri = new IRI("http://example.org/custom");
+ TcManager.getInstance().getTcAccessController().setRequiredReadPermissionStrings(graphUri,
+ Collections.singletonList("(java.io.FilePermission \"/etc\" \"write\")"));
+ //new FilePermission("/etc", "write").toString()));
+ Graph ag = TcManager.getInstance().getGraph(new IRI("urn:x-localinstance:/graph-access.graph"));
+ System.out.print(ag.toString());
+ TcManager.getInstance().getMGraph(graphUri);
+ }
+
+ @Test(expected=AccessControlException.class)
+ public void testCustomPermissionsIncorrect() {
+ IRI graphUri = new IRI("http://example.org/custom");
+ TcManager.getInstance().getTcAccessController().setRequiredReadPermissionStrings(graphUri,
+ Collections.singletonList("(java.io.FilePermission \"/etc\" \"write\")"));
+ //new FilePermission("/etc", "write").toString()));
+ Graph ag = TcManager.getInstance().getGraph(new IRI("urn:x-localinstance:/graph-access.graph"));
+ System.out.print(ag.toString());
+ TcManager.getInstance().createGraph(graphUri);
+ }
+
+ @Test
+ public void testCustomReadWritePermissions() {
+ IRI graphUri = new IRI("http://example.org/read-write-custom");
+ TcManager.getInstance().getTcAccessController().setRequiredReadWritePermissionStrings(graphUri,
+ Collections.singletonList("(java.io.FilePermission \"/etc\" \"write\")"));
+ //new FilePermission("/etc", "write").toString()));
+ Graph ag = TcManager.getInstance().getGraph(new IRI("urn:x-localinstance:/graph-access.graph"));
+ System.out.print(ag.toString());
+ TcManager.getInstance().createGraph(graphUri);
+ }
+
+ @Test(expected=EntityAlreadyExistsException.class)
+ public void testCreateMGraph() {
+ TcManager.getInstance().createGraph(new IRI("http://example.org/ImmutableGraph/alreadyexists"));
+ }
+ @Test(expected=AccessControlException.class)
+ public void testCreateMGraphWithoutWritePermission() {
+ TcManager.getInstance().createGraph(new IRI("http://example.org/read/ImmutableGraph"));
+ }
+ @Test(expected=ReadOnlyException.class)
+ public void testAddTripleToMGraph() {
+ Graph graph = TcManager.getInstance().getMGraph(new IRI("http://example.org/read/ImmutableGraph"));
+ Triple triple = new TripleImpl(
+ new IRI("http://example.org/definition/isNonLiteral"),
+ new IRI("http://example.org/definition/isTest"),
+ new PlainLiteralImpl("test"));
+ graph.add(triple);
+ }
+}
\ No newline at end of file
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/TcManagerTest.java b/dataset/src/test/java/org/apache/clerezza/dataset/TcManagerTest.java
new file mode 100644
index 0000000..619e86a
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/TcManagerTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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.dataset;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.Triple;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.graph.SimpleMGraph;
+import org.apache.clerezza.dataset.providers.WeightedA;
+import org.apache.clerezza.dataset.providers.WeightedA1;
+import org.apache.clerezza.dataset.providers.WeightedAHeavy;
+import org.apache.clerezza.dataset.providers.WeightedBlight;
+import org.apache.clerezza.sparql.NoQueryEngineException;
+import org.apache.clerezza.sparql.QueryEngine;
+import org.apache.clerezza.sparql.query.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Field;
+import java.util.Iterator;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author reto
+ */
+public class TcManagerTest {
+
+ public static IRI uriRefAHeavy = new IRI("http://example.org/aHeavy");
+ public static IRI uriRefB = new IRI("http://example.org/b");;
+ public static final IRI uriRefA = new IRI("http://example.org/a");
+ public static final IRI uriRefA1 = new IRI("http://example.org/a1");
+ private TcManager graphAccess;
+ private QueryEngine queryEngine;
+ private final WeightedA weightedA = new WeightedA();
+ private final WeightedA1 weightedA1 = new WeightedA1();
+ private WeightedTcProvider weightedBlight = new WeightedBlight();
+
+ @Before
+ public void setUp() {
+ graphAccess = TcManager.getInstance();
+ graphAccess.bindWeightedTcProvider(weightedA);
+ graphAccess.bindWeightedTcProvider(weightedA1);
+ graphAccess.bindWeightedTcProvider(weightedBlight);
+
+ queryEngine = Mockito.mock(QueryEngine.class);
+ }
+
+ @After
+ public void tearDown() {
+ graphAccess = TcManager.getInstance();
+ graphAccess.unbindWeightedTcProvider(weightedA);
+ graphAccess.unbindWeightedTcProvider(weightedA1);
+ graphAccess.unbindWeightedTcProvider(weightedBlight);
+
+ queryEngine = null;
+ }
+
+ @Test
+ public void getGraphFromA() {
+ ImmutableGraph graphA = graphAccess.getImmutableGraph(uriRefA);
+ Iterator<Triple> iterator = graphA.iterator();
+ assertEquals(new TripleImpl(uriRefA, uriRefA, uriRefA), iterator.next());
+ assertFalse(iterator.hasNext());
+ Graph triplesA = graphAccess.getGraph(uriRefA);
+ iterator = triplesA.iterator();
+ assertEquals(new TripleImpl(uriRefA, uriRefA, uriRefA), iterator.next());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void getGraphFromB() {
+ ImmutableGraph graphA = graphAccess.getImmutableGraph(uriRefB);
+ Iterator<Triple> iterator = graphA.iterator();
+ assertEquals(new TripleImpl(uriRefB, uriRefB, uriRefB), iterator.next());
+ assertFalse(iterator.hasNext());
+ Graph triplesA = graphAccess.getGraph(uriRefB);
+ iterator = triplesA.iterator();
+ assertEquals(new TripleImpl(uriRefB, uriRefB, uriRefB), iterator.next());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void getGraphFromAAfterUnbinding() {
+ graphAccess.unbindWeightedTcProvider(weightedA);
+ ImmutableGraph graphA = graphAccess.getImmutableGraph(uriRefA);
+ Iterator<Triple> iterator = graphA.iterator();
+ assertEquals(new TripleImpl(uriRefA1, uriRefA1, uriRefA1),
+ iterator.next());
+ assertFalse(iterator.hasNext());
+ Graph triplesA = graphAccess.getGraph(uriRefA);
+ iterator = triplesA.iterator();
+ assertEquals(new TripleImpl(uriRefA1, uriRefA1, uriRefA1),
+ iterator.next());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void getGraphFromAWithHeavy() {
+ final WeightedAHeavy weightedAHeavy = new WeightedAHeavy();
+ graphAccess.bindWeightedTcProvider(weightedAHeavy);
+ ImmutableGraph graphA = graphAccess.getImmutableGraph(uriRefA);
+ Iterator<Triple> iterator = graphA.iterator();
+ assertEquals(new TripleImpl(uriRefAHeavy, uriRefAHeavy, uriRefAHeavy),
+ iterator.next());
+ assertFalse(iterator.hasNext());
+ Graph triplesA = graphAccess.getGraph(uriRefA);
+ iterator = triplesA.iterator();
+ assertEquals(new TripleImpl(uriRefAHeavy, uriRefAHeavy, uriRefAHeavy),
+ iterator.next());
+ assertFalse(iterator.hasNext());
+ graphAccess.unbindWeightedTcProvider(weightedAHeavy);
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithString() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess.executeSparqlQuery("", new SimpleMGraph());
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess.executeSparqlQuery((Query) null, new SimpleMGraph());
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithSelectQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess.executeSparqlQuery((SelectQuery) null, new SimpleMGraph());
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithAskQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess.executeSparqlQuery((AskQuery) null, new SimpleMGraph());
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithDescribeQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess
+ .executeSparqlQuery((DescribeQuery) null, new SimpleMGraph());
+ }
+
+ @Test(expected = NoQueryEngineException.class)
+ public void executeSparqlQueryNoEngineWithConstructQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(null);
+
+ // Execute
+ graphAccess.executeSparqlQuery((ConstructQuery) null,
+ new SimpleMGraph());
+ }
+
+ @Test
+ public void executeSparqlQueryWithEngineWithString() throws Exception {
+ // Prepare
+ injectQueryEngine(queryEngine);
+ Graph Graph = new SimpleMGraph();
+
+ // Execute
+ graphAccess.executeSparqlQuery("", Graph);
+
+ // Verify
+ Mockito.verify(queryEngine).execute(graphAccess, Graph, "");
+// Mockito.verify(queryEngine, Mockito.never()).execute(
+// (TcManager) Mockito.anyObject(),
+// (Graph) Mockito.anyObject(),
+// Mockito.anyString());
+ }
+
+ @Test
+ public void executeSparqlQueryWithEngineWithSelectQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(queryEngine);
+ Graph Graph = new SimpleMGraph();
+ SelectQuery query = Mockito.mock(SelectQuery.class);
+
+ // Execute
+ graphAccess.executeSparqlQuery(query, Graph);
+
+ // Verify
+ Mockito.verify(queryEngine).execute(graphAccess, Graph,
+ query.toString());
+// Mockito.verify(queryEngine, Mockito.never()).execute(
+// (TcManager) Mockito.anyObject(),
+// (Graph) Mockito.anyObject(), Mockito.anyString());
+ }
+
+ @Test
+ public void executeSparqlQueryWithEngineWithAskQuery() throws Exception {
+ // Prepare
+ injectQueryEngine(queryEngine);
+ Graph Graph = new SimpleMGraph();
+ AskQuery query = Mockito.mock(AskQuery.class);
+
+ Mockito.when(
+ queryEngine.execute((TcManager) Mockito.anyObject(),
+ (Graph) Mockito.anyObject(),
+ Mockito.anyString())).thenReturn(Boolean.TRUE);
+
+ // Execute
+ graphAccess.executeSparqlQuery(query, Graph);
+
+ // Verify
+ Mockito.verify(queryEngine).execute(graphAccess, Graph,
+ query.toString());
+// Mockito.verify(queryEngine, Mockito.never()).execute(
+// (TcManager) Mockito.anyObject(),
+// (Graph) Mockito.anyObject(), Mockito.anyString());
+ }
+
+ @Test
+ public void executeSparqlQueryWithEngineWithDescribeQuery()
+ throws Exception {
+ // Prepare
+ injectQueryEngine(queryEngine);
+ Graph Graph = new SimpleMGraph();
+ DescribeQuery query = Mockito.mock(DescribeQuery.class);
+
+ // Execute
+ graphAccess.executeSparqlQuery(query, Graph);
+
+ // Verify
+ Mockito.verify(queryEngine).execute(graphAccess, Graph,
+ query.toString());
+// Mockito.verify(queryEngine, Mockito.never()).execute(
+// (TcManager) Mockito.anyObject(),
+// (Graph) Mockito.anyObject(), Mockito.anyString());
+ }
+
+ @Test
+ public void executeSparqlQueryWithEngineWithConstructQuery()
+ throws Exception {
+ // Prepare
+ injectQueryEngine(queryEngine);
+ Graph Graph = new SimpleMGraph();
+ ConstructQuery query = Mockito.mock(ConstructQuery.class);
+
+ // Execute
+ graphAccess.executeSparqlQuery(query, Graph);
+
+ // Verify
+ Mockito.verify(queryEngine).execute(graphAccess, Graph,
+ query.toString());
+// Mockito.verify(queryEngine, Mockito.never()).execute(
+// (TcManager) Mockito.anyObject(),
+// (Graph) Mockito.anyObject(), Mockito.anyString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementing QueryableTcProvider
+ // ------------------------------------------------------------------------
+
+ private void injectQueryEngine(QueryEngine engine)
+ throws NoSuchFieldException, IllegalAccessException {
+ Field queryEngineField = TcManager.class
+ .getDeclaredField("queryEngine");
+ queryEngineField.setAccessible(true);
+ queryEngineField.set(graphAccess, engine);
+ }
+}
\ No newline at end of file
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA.java b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA.java
new file mode 100644
index 0000000..76b6f36
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA.java
@@ -0,0 +1,103 @@
+/*
+ * 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.dataset.providers;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.graph.SimpleMGraph;
+import org.apache.clerezza.dataset.EntityUndeletableException;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.TcManagerTest;
+import org.apache.clerezza.dataset.WeightedTcProvider;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author reto
+ */
+public class WeightedA implements WeightedTcProvider {
+ private Set<IRI> mGraphList = new HashSet<IRI>();
+ @Override
+ public int getWeight() {
+ return 5;
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ if (name.equals(TcManagerTest.uriRefA)) {
+ Graph mResult = new SimpleMGraph();
+ mResult.add(new TripleImpl(TcManagerTest.uriRefA,
+ TcManagerTest.uriRefA, TcManagerTest.uriRefA));
+ mGraphList.add(name);
+ return mResult.getImmutableGraph();
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) throws NoSuchEntityException {
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name) throws NoSuchEntityException {
+ return getImmutableGraph(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void deleteGraph(IRI name) throws NoSuchEntityException,
+ EntityUndeletableException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ return Collections.singleton(TcManagerTest.uriRefA);
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ return mGraphList;
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ return listGraphs();
+ }
+}
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA1.java b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA1.java
new file mode 100644
index 0000000..effd599
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedA1.java
@@ -0,0 +1,103 @@
+/*
+ * 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.dataset.providers;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.graph.SimpleMGraph;
+import org.apache.clerezza.dataset.EntityUndeletableException;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.TcManagerTest;
+import org.apache.clerezza.dataset.WeightedTcProvider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Same weight as WeightedA, but later in string-ordering
+ *
+ * @author reto
+ */
+public class WeightedA1 implements WeightedTcProvider {
+ private Set<IRI> mGraphList = new HashSet<IRI>();
+ @Override
+ public int getWeight() {
+ return 5;
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ if (name.equals(TcManagerTest.uriRefA)) {
+ Graph mResult = new SimpleMGraph();
+ mResult.add(new TripleImpl(TcManagerTest.uriRefA1,
+ TcManagerTest.uriRefA1, TcManagerTest.uriRefA1));
+ mGraphList.add(name);
+ return mResult.getImmutableGraph();
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) throws NoSuchEntityException {
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name) throws NoSuchEntityException {
+ return getImmutableGraph(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void deleteGraph(IRI name) throws NoSuchEntityException,
+ EntityUndeletableException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ return mGraphList;
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ return listMGraphs();
+ }
+}
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedAHeavy.java b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedAHeavy.java
new file mode 100644
index 0000000..3cc1421
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedAHeavy.java
@@ -0,0 +1,101 @@
+/*
+ * 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.dataset.providers;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.graph.SimpleGraph;
+import org.apache.clerezza.dataset.EntityUndeletableException;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.TcManagerTest;
+import org.apache.clerezza.dataset.WeightedTcProvider;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author reto
+ */
+public class WeightedAHeavy implements WeightedTcProvider {
+
+ @Override
+ public int getWeight() {
+ return 20;
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ if (name.equals(TcManagerTest.uriRefA)) {
+ Graph mResult = new SimpleGraph();
+ mResult.add(new TripleImpl(TcManagerTest.uriRefAHeavy,
+ TcManagerTest.uriRefAHeavy, TcManagerTest.uriRefAHeavy));
+ return mResult.getImmutableGraph();
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) throws NoSuchEntityException {
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name) throws NoSuchEntityException {
+ return getImmutableGraph(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void deleteGraph(IRI name) throws NoSuchEntityException,
+ EntityUndeletableException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ @Override
+ public Set<IRI> listGraphs() {
+ return Collections.singleton(TcManagerTest.uriRefA);
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ return new HashSet<IRI>();
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ return listGraphs();
+ }
+}
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedBlight.java b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedBlight.java
new file mode 100644
index 0000000..161599b
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedBlight.java
@@ -0,0 +1,106 @@
+/*
+ * 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.dataset.providers;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.TripleImpl;
+import org.apache.clerezza.api.impl.graph.SimpleMGraph;
+import org.apache.clerezza.dataset.EntityUndeletableException;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.TcManagerTest;
+import org.apache.clerezza.dataset.WeightedTcProvider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author reto
+ */
+public class WeightedBlight implements WeightedTcProvider {
+
+ @Override
+ public int getWeight() {
+ return 2;
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ if (name.equals(TcManagerTest.uriRefB)) {
+ Graph mResult = new SimpleMGraph();
+ mResult.add(new TripleImpl(TcManagerTest.uriRefB, TcManagerTest.uriRefB, TcManagerTest.uriRefB));
+ return mResult.getImmutableGraph();
+ }
+ if (name.equals(TcManagerTest.uriRefA)) {
+ Graph mResult = new SimpleMGraph();
+ //empty ImmutableGraph
+ return mResult.getImmutableGraph();
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) throws NoSuchEntityException {
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getGraph(IRI name) throws NoSuchEntityException {
+ return getImmutableGraph(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void deleteGraph(IRI name) throws NoSuchEntityException,
+ EntityUndeletableException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ return new HashSet<IRI>();
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ return listMGraphs();
+ }
+
+}
diff --git a/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedDummy.java b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedDummy.java
new file mode 100644
index 0000000..44ace0e
--- /dev/null
+++ b/dataset/src/test/java/org/apache/clerezza/dataset/providers/WeightedDummy.java
@@ -0,0 +1,155 @@
+/*
+ * 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.dataset.providers;
+
+import org.apache.clerezza.api.Graph;
+import org.apache.clerezza.api.IRI;
+import org.apache.clerezza.api.ImmutableGraph;
+import org.apache.clerezza.api.impl.graph.SimpleImmutableGraph;
+import org.apache.clerezza.api.impl.graph.SimpleMGraph;
+import org.apache.clerezza.dataset.EntityAlreadyExistsException;
+import org.apache.clerezza.dataset.EntityUndeletableException;
+import org.apache.clerezza.dataset.NoSuchEntityException;
+import org.apache.clerezza.dataset.WeightedTcProvider;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author mir
+ */
+public class WeightedDummy implements WeightedTcProvider {
+
+ private Map<IRI, Graph> tripleMap = new HashMap<IRI, Graph>();
+
+ @Override
+ public ImmutableGraph createImmutableGraph(IRI name, Graph triples)
+ throws EntityAlreadyExistsException {
+ if ((name == null) || (name.getUnicodeString() == null)
+ || (name.getUnicodeString().trim().length() == 0)) {
+ throw new IllegalArgumentException("Name must not be null");
+ }
+
+ try {
+ // throws NoSuchEntityException if a Graph with that name
+ // already exists
+ this.getGraph(name);
+ } catch (NoSuchEntityException e) {
+ ImmutableGraph result;
+ if (ImmutableGraph.class.isAssignableFrom(triples.getClass())) {
+ result = (ImmutableGraph) triples;
+ } else {
+ result = new SimpleImmutableGraph(triples);
+ }
+ tripleMap.put(name, result);
+
+ return result;
+ }
+ throw new EntityAlreadyExistsException(name);
+ }
+
+ @Override
+ public Graph createGraph(IRI name) throws EntityAlreadyExistsException {
+ if ((name == null) || (name.getUnicodeString() == null)
+ || (name.getUnicodeString().trim().length() == 0)) {
+ throw new IllegalArgumentException("Name must not be null");
+ }
+
+ try {
+ // throws NoSuchEntityException if a Graph with that name
+ // already exists
+ this.getGraph(name);
+ } catch (NoSuchEntityException e) {
+ Graph result = new SimpleMGraph();
+ tripleMap.put(name, result);
+ return result;
+ }
+ throw new EntityAlreadyExistsException(name);
+ }
+
+ @Override
+ public void deleteGraph(IRI name)
+ throws NoSuchEntityException, EntityUndeletableException {
+ if (tripleMap.remove(name) == null) {
+ throw new NoSuchEntityException(name);
+ }
+ }
+
+ @Override
+ public ImmutableGraph getImmutableGraph(IRI name) throws NoSuchEntityException {
+ Graph Graph = tripleMap.get(name);
+ if (Graph == null) {
+ throw new NoSuchEntityException(name);
+ } else if (ImmutableGraph.class.isAssignableFrom(Graph.getClass())) {
+ return (ImmutableGraph) Graph;
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Graph getMGraph(IRI name) throws NoSuchEntityException {
+ Graph Graph = tripleMap.get(name);
+ if (Graph == null) {
+ throw new NoSuchEntityException(name);
+ } else if (Graph.class.isAssignableFrom(Graph.getClass())) {
+ return (Graph) Graph;
+ }
+ throw new NoSuchEntityException(name);
+ }
+
+ @Override
+ public Set<IRI> getNames(ImmutableGraph ImmutableGraph) {
+ throw new UnsupportedOperationException(
+ "Not supported yet. equals() has to be implemented first");
+ }
+
+ @Override
+ public Graph getGraph(IRI name)
+ throws NoSuchEntityException {
+ Graph Graph = tripleMap.get(name);
+ if (Graph == null) {
+ throw new NoSuchEntityException(name);
+ } else {
+ return Graph;
+ }
+ }
+
+ @Override
+ public int getWeight() {
+ return 1;
+ }
+
+ @Override
+ public Set<IRI> listImmutableGraphs() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Set<IRI> listMGraphs() {
+ return new HashSet<IRI>();
+ }
+
+ @Override
+ public Set<IRI> listGraphs() {
+ return listMGraphs();
+ }
+}