You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2013/02/19 13:52:00 UTC
[33/52] [partial] code contribution,
initial import of relevant modules of LMF-3.0.0-SNAPSHOT based on
revision 4bf944319368 of the default branch at https://code.google.com/p/lmf/
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/pom.xml
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/pom.xml b/ldcache/ldcache-sail-kiwi/pom.xml
new file mode 100644
index 0000000..8d728fd
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/pom.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2013 The Apache Software Foundation
+ ~
+ ~ Licensed 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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <artifactId>ldcache-sail-kiwi</artifactId>
+ <name>LDCache: Sesame SAIL (KiWi)</name>
+
+ <description>
+ Stacked Sail that allows transparent access to resources through the Linked Data Cache, retrieving them
+ on demand when needed. Can be wrapped around other Sesame SAILs.
+ </description>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <h2.url>jdbc:h2:mem:test;MVCC=true;DB_CLOSE_ON_EXIT=TRUE</h2.url>
+ <h2.user>sa</h2.user>
+ <h2.pass />
+
+ <!-- enable or pass on command line for testing local PostgreSQL -->
+ <!--
+ <postgresql.url>jdbc:postgresql://localhost:5433/kiwitest?prepareThreshold=3</postgresql.url>
+ <postgresql.user>lmf</postgresql.user>
+ <postgresql.pass>lmf</postgresql.pass>
+ -->
+
+ <!-- enable or pass on command line for testing local MySQL -->
+ <!--
+ <mysql.url>jdbc:mysql://localhost:3306/kiwitest</mysql.url>
+ <mysql.user>lmf</mysql.user>
+ <mysql.pass>lmf</mysql.pass>
+ -->
+
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-backend-kiwi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>kiwi-triplestore</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-repository-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.sesame</groupId>
+ <artifactId>sesame-commons</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.sesame</groupId>
+ <artifactId>sesame-filter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+
+ <!-- LDClient -->
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldclient-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldclient-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldclient-provider-rdf</artifactId>
+ </dependency>
+
+
+ <!-- logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jul-to-slf4j</artifactId>
+ </dependency>
+
+
+ <!-- Testing -->
+ <dependency>
+ <artifactId>junit</artifactId>
+ <groupId>junit</groupId>
+ <scope>test</scope>
+ </dependency>
+ <dependency> <!-- see http://www.dbunit.org/howto.html -->
+ <artifactId>dbunit</artifactId>
+ <groupId>org.dbunit</groupId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <artifactId>hamcrest-core</artifactId>
+ <groupId>org.hamcrest</groupId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <artifactId>hamcrest-library</artifactId>
+ <groupId>org.hamcrest</groupId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-rio-turtle</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSail.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSail.java b/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSail.java
new file mode 100644
index 0000000..5d29659
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSail.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldcache.sail;
+
+import org.apache.marmotta.kiwi.sail.KiWiStore;
+import org.apache.marmotta.ldcache.backend.kiwi.LDCachingKiWiBackend;
+import org.apache.marmotta.ldcache.model.CacheConfiguration;
+import org.apache.marmotta.ldcache.services.LDCache;
+import org.apache.marmotta.ldclient.model.ClientConfiguration;
+import org.apache.marmotta.sesame.filter.SesameFilter;
+import org.openrdf.model.Resource;
+import org.openrdf.sail.NotifyingSail;
+import org.openrdf.sail.NotifyingSailConnection;
+import org.openrdf.sail.SailException;
+import org.openrdf.sail.StackableSail;
+import org.openrdf.sail.helpers.NotifyingSailWrapper;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class KiWiLinkedDataSail extends NotifyingSailWrapper {
+
+ private KiWiStore store;
+
+ private LDCachingKiWiBackend backend;
+
+ private LDCache ldcache;
+
+ private SesameFilter<Resource> acceptor;
+
+ private String cache_context;
+
+ private CacheConfiguration config;
+
+ /**
+ * Creates a new SAIL with transparent Linked Data access. Caching information is stored in the underlying
+ * KiWi triple store.
+ *
+ * @param baseSail the wrapped SAIL; at the parent level must be a KiWiStore
+ * @param acceptor a filter that selects which resources are considered as external Linked Data resources,
+ * e.g. all resources not matching http://localhost and file:
+ * @param cacheContextUri the URI of the context to use for storing cached triples
+ */
+ public KiWiLinkedDataSail(NotifyingSail baseSail, SesameFilter<Resource> acceptor, String cacheContextUri) {
+ this(baseSail, acceptor, cacheContextUri,null);
+ }
+
+ /**
+ * Creates a new SAIL with transparent Linked Data access. Caching information is stored in the underlying
+ * KiWi triple store.
+ *
+ * @param baseSail the wrapped SAIL; at the parent level must be a KiWiStore
+ * @param acceptor a filter that selects which resources are considered as external Linked Data resources,
+ * e.g. all resources not matching http://localhost and file:
+ * @param cacheContextUri the URI of the context to use for storing cached triples
+ */
+ public KiWiLinkedDataSail(NotifyingSail baseSail, SesameFilter<Resource> acceptor, String cacheContextUri, ClientConfiguration clientConfiguration) {
+ super(baseSail);
+
+ this.store = getBaseStore();
+ this.cache_context = cacheContextUri;
+ this.acceptor = acceptor;
+ this.config = new CacheConfiguration();
+ if(clientConfiguration != null) {
+ config.setClientConfiguration(clientConfiguration);
+ }
+ }
+
+
+ @Override
+ public void initialize() throws SailException {
+ super.initialize();
+
+ backend = new LDCachingKiWiBackend(store, cache_context);
+ backend.initialize();
+
+ ldcache = new LDCache(config,backend);
+
+ }
+
+ @Override
+ public void shutDown() throws SailException {
+ ldcache.shutdown();
+ backend.shutdown();
+
+ super.shutDown();
+ }
+
+ @Override
+ public NotifyingSailConnection getConnection() throws SailException {
+ return new KiWiLinkedDataSailConnection(super.getConnection(),ldcache,acceptor);
+ }
+
+ /**
+ * Return the KiWi store that is at the base of the SAIL stack. Throws an IllegalArgumentException in case the base
+ * store is not a KiWi store.
+ *
+ * @return
+ */
+ public KiWiStore getBaseStore() {
+ StackableSail current = this;
+ while(current != null && current.getBaseSail() instanceof StackableSail) {
+ current = (StackableSail) current.getBaseSail();
+ }
+ if(current != null && current.getBaseSail() instanceof KiWiStore) {
+ return (KiWiStore) current.getBaseSail();
+ } else {
+ throw new IllegalStateException("the base store is not a KiWiStore (type: "+current.getBaseSail().getClass().getCanonicalName()+")!");
+ }
+ }
+
+ public LDCachingKiWiBackend getBackend() {
+ return backend;
+ }
+
+ public LDCache getLDCache() {
+ return ldcache;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSailConnection.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSailConnection.java b/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSailConnection.java
new file mode 100644
index 0000000..07e0c3c
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/main/java/org/apache/marmotta/ldcache/sail/KiWiLinkedDataSailConnection.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldcache.sail;
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.marmotta.ldcache.services.LDCache;
+import org.apache.marmotta.sesame.filter.SesameFilter;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.sail.NotifyingSailConnection;
+import org.openrdf.sail.SailException;
+import org.openrdf.sail.helpers.NotifyingSailConnectionWrapper;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class KiWiLinkedDataSailConnection extends NotifyingSailConnectionWrapper {
+
+ private LDCache ldcache;
+
+ private SesameFilter<Resource> acceptor;
+
+ public KiWiLinkedDataSailConnection(NotifyingSailConnection wrappedCon, LDCache ldcache, SesameFilter<Resource> acceptor) {
+ super(wrappedCon);
+
+ this.ldcache = ldcache;
+ this.acceptor = acceptor;
+ }
+
+
+ /**
+ * Handle a triple store query event. This method carries out the following steps:
+ * 1. if the subject of the query is local, return immediately without doing anything
+ * 2. if the subject of the query is a remote resource, call refreshResource on it; refreshed triples will
+ * be part of the currently active transaction and thus be available to the listTriples method execution
+ * 3, if the subject of the query is null, refresh all non-local resources in the triple store
+ */
+ @Override
+ public CloseableIteration<? extends Statement, SailException> getStatements(Resource subj, URI pred, Value obj, boolean includeInferred, Resource... contexts) throws SailException {
+ if(subj != null && isAcceptable(subj)) {
+ ldcache.refreshResource((URI)subj,false);
+ }
+
+ // the refreshed resources will anyways be stored in the same triple store, so we can simply delegate the query
+ // to the wrapped repository
+
+ return super.getStatements(subj, pred, obj, includeInferred, contexts);
+ }
+
+
+ private boolean isAcceptable(Resource resource) {
+ if(resource instanceof BNode) {
+ return false;
+ }
+ return acceptor.accept(resource);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/KiWiLinkedDataSailOfflineTest.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/KiWiLinkedDataSailOfflineTest.java b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/KiWiLinkedDataSailOfflineTest.java
new file mode 100644
index 0000000..72b73b0
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/KiWiLinkedDataSailOfflineTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed 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.marmotta.ldcache.sail.test;
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.persistence.h2.H2Dialect;
+import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
+import org.apache.marmotta.kiwi.persistence.pgsql.PostgreSQLDialect;
+import org.apache.marmotta.kiwi.sail.KiWiStore;
+import org.apache.marmotta.ldcache.sail.KiWiLinkedDataSail;
+import org.apache.marmotta.ldcache.sail.test.dummy.DummyEndpoint;
+import org.apache.marmotta.ldclient.model.ClientConfiguration;
+import org.apache.marmotta.sesame.filter.resource.ResourceFilter;
+import org.apache.marmotta.sesame.filter.resource.UriPrefixFilter;
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.openrdf.model.Statement;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.hasToString;
+
+
+/**
+ * This test checks if the transparent linked data caching works, based on an ldclient offline provider. It will try
+ * running over all available databases. Except for in-memory databases like
+ * H2 or Derby, database URLs must be passed as system property, or otherwise the test is skipped for this database.
+ * Available system properties:
+ * <ul>
+ * <li>PostgreSQL:
+ * <ul>
+ * <li>postgresql.url, e.g. jdbc:postgresql://localhost:5433/kiwitest?prepareThreshold=3</li>
+ * <li>postgresql.user (default: lmf)</li>
+ * <li>postgresql.pass (default: lmf)</li>
+ * </ul>
+ * </li>
+ * <li>MySQL:
+ * <ul>
+ * <li>mysql.url, e.g. jdbc:mysql://localhost:3306/kiwitest?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull</li>
+ * <li>mysql.user (default: lmf)</li>
+ * <li>mysql.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * <li>H2:
+ * <ul>
+ * <li>h2.url, e.g. jdbc:h2:mem;MVCC=true;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=10</li>
+ * <li>h2.user (default: lmf)</li>
+ * <li>h2.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@RunWith(Parameterized.class)
+public class KiWiLinkedDataSailOfflineTest {
+
+ private static final String CACHE_CONTEXT = "http://localhost/context/cache";
+
+ /**
+ * Return database configurations if the appropriate parameters have been set.
+ *
+ * @return an array (database name, url, user, password)
+ */
+ @Parameterized.Parameters(name="Database Test {index}: {0} at {1}")
+ public static Iterable<Object[]> databases() {
+ String[] databases = {"H2", "PostgreSQL", "MySQL"};
+
+ List<Object[]> result = new ArrayList<Object[]>(databases.length);
+ for(String database : databases) {
+ if(System.getProperty(database.toLowerCase()+".url") != null) {
+ result.add(new Object[] {
+ database,
+ System.getProperty(database.toLowerCase()+".url"),
+ System.getProperty(database.toLowerCase()+".user","lmf"),
+ System.getProperty(database.toLowerCase()+".pass","lmf")
+ });
+ }
+ }
+ return result;
+ }
+
+
+ private KiWiDialect dialect;
+
+ private String jdbcUrl;
+
+ private String jdbcUser;
+
+ private String jdbcPass;
+
+ private KiWiStore store;
+
+ private KiWiLinkedDataSail lsail;
+
+ private ResourceFilter cacheFilter;
+
+ private Repository repository;
+
+ public KiWiLinkedDataSailOfflineTest(String database, String jdbcUrl, String jdbcUser, String jdbcPass) {
+ this.jdbcPass = jdbcPass;
+ this.jdbcUrl = jdbcUrl;
+ this.jdbcUser = jdbcUser;
+
+ if("H2".equals(database)) {
+ this.dialect = new H2Dialect();
+ } else if("MySQL".equals(database)) {
+ this.dialect = new MySQLDialect();
+ } else if("PostgreSQL".equals(database)) {
+ this.dialect = new PostgreSQLDialect();
+ }
+ }
+
+
+ @Before
+ public void initDatabase() throws RepositoryException {
+ cacheFilter = new UriPrefixFilter("http://remote/");
+
+ ClientConfiguration config = new ClientConfiguration();
+ config.addEndpoint(new DummyEndpoint());
+
+ store = new KiWiStore("test",jdbcUrl,jdbcUser,jdbcPass,dialect, "http://localhost/context/default", "http://localhost/context/inferred");
+ lsail = new KiWiLinkedDataSail(store,cacheFilter,CACHE_CONTEXT, config);
+ repository = new SailRepository(lsail);
+ repository.initialize();
+ }
+
+ @After
+ public void dropDatabase() throws RepositoryException, SQLException {
+ store.closeValueFactory();
+ lsail.getBackend().getPersistence().dropDatabase();
+ store.getPersistence().dropDatabase();
+ repository.shutDown();
+ }
+
+ /**
+ * This test verifies whether the transparent caching works for the three resources provided by our
+ * dummy provider.
+ * @throws Exception
+ */
+ @Test
+ public void testCachedResources() throws Exception {
+ String uri1 = "http://remote/resource1";
+ String uri2 = "http://remote/resource2";
+ String uri3 = "http://remote/resource3";
+
+ RepositoryConnection con = repository.getConnection();
+ try {
+ con.begin();
+
+ List<Statement> list1 = asList(con.getStatements(con.getValueFactory().createURI(uri1), null, null, true));
+
+ Assert.assertEquals(3,list1.size());
+ Assert.assertThat(list1, allOf(
+ CoreMatchers.<Statement>hasItem(hasProperty("object", hasToString("\"Value 1\"^^xsd:string"))),
+ CoreMatchers.<Statement>hasItem(hasProperty("object", hasToString("\"Value X\"^^xsd:string")))
+ ));
+
+
+ con.commit();
+
+ con.begin();
+
+ List<Statement> list2 = asList(con.getStatements(con.getValueFactory().createURI(uri2), null, null, true));
+
+ Assert.assertEquals(2, list2.size());
+ Assert.assertThat(list2, allOf(
+ CoreMatchers.<Statement>hasItem(hasProperty("object", hasToString("\"Value 2\"^^xsd:string")))
+ ));
+
+
+ con.commit();
+
+ con.begin();
+
+ List<Statement> list3 = asList(con.getStatements(con.getValueFactory().createURI(uri3), null, null, true));
+
+ Assert.assertEquals(2, list3.size());
+ Assert.assertThat(list3, allOf(
+ CoreMatchers.<Statement>hasItem(hasProperty("object", hasToString("\"Value 3\"^^xsd:string"))),
+ CoreMatchers.<Statement>hasItem(hasProperty("object", hasToString("\"Value 4\"^^xsd:string")))
+ ));
+
+
+ con.commit();
+ } catch(RepositoryException ex) {
+ con.rollback();
+ } finally {
+ con.close();
+ }
+ }
+
+ /**
+ * Workaround for https://openrdf.atlassian.net/browse/SES-1702 in Sesame 2.7.0-beta1
+ * @param <E>
+ * @return
+ */
+ public static <E,X extends Exception> List<E> asList(CloseableIteration<E,X> result) throws RepositoryException {
+ ArrayList<E> collection = new ArrayList<E>();
+ try {
+ try {
+ while (result.hasNext()) {
+ collection.add(result.next());
+ }
+
+ return collection;
+ } finally {
+ result.close();
+ }
+ } catch(Throwable ex) {
+ throw new RepositoryException(ex);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyEndpoint.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyEndpoint.java b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyEndpoint.java
new file mode 100644
index 0000000..d4c758e
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyEndpoint.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed 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.marmotta.ldcache.sail.test.dummy;
+
+import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
+
+public class DummyEndpoint extends Endpoint {
+
+ public DummyEndpoint() {
+ super("Dummy", "Dummy", "^http://remote", null, 86400l);
+ setPriority(PRIORITY_HIGH);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyProvider.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyProvider.java b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyProvider.java
new file mode 100644
index 0000000..4a0bcd3
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyProvider.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed 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.marmotta.ldcache.sail.test.dummy;
+
+import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
+import org.apache.marmotta.ldclient.api.ldclient.LDClientService;
+import org.apache.marmotta.ldclient.api.provider.DataProvider;
+import org.apache.marmotta.ldclient.exception.DataRetrievalException;
+import org.apache.marmotta.ldclient.model.ClientResponse;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFParseException;
+import org.openrdf.sail.memory.MemoryStore;
+
+import java.io.IOException;
+
+public class DummyProvider implements DataProvider {
+
+ @Override
+ public String getName() {
+ return "Dummy";
+ }
+
+ @Override
+ public String[] listMimeTypes() {
+ return new String[] {"application/dummy"};
+ }
+
+ @Override
+ public ClientResponse retrieveResource(String resource, LDClientService client, Endpoint endpoint) throws DataRetrievalException {
+ String filename = resource.substring("http://remote/".length()) + ".ttl";
+
+ try {
+ Repository triples = new SailRepository(new MemoryStore());
+ triples.initialize();
+
+ RepositoryConnection con = triples.getConnection();
+ try {
+ con.begin();
+
+ con.add(DummyProvider.class.getResourceAsStream(filename), resource, RDFFormat.TURTLE);
+
+ con.commit();
+ } catch(RepositoryException ex) {
+ con.rollback();
+ } catch (RDFParseException e) {
+ throw new DataRetrievalException("could not parse resource data for file "+filename);
+ } catch (IOException e) {
+ throw new DataRetrievalException("could not load resource data for file "+filename);
+ } finally {
+ con.close();
+ }
+
+ ClientResponse response = new ClientResponse(triples);
+
+ return response;
+ } catch (RepositoryException e) {
+ throw new DataRetrievalException("could not load resource data for file "+filename);
+ }
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyTest.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyTest.java b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyTest.java
new file mode 100644
index 0000000..ab5ea29
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/java/org/apache/marmotta/ldcache/sail/test/dummy/DummyTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed 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.marmotta.ldcache.sail.test.dummy;
+
+import org.apache.marmotta.ldclient.api.ldclient.LDClientService;
+import org.apache.marmotta.ldclient.model.ClientConfiguration;
+import org.apache.marmotta.ldclient.model.ClientResponse;
+import org.apache.marmotta.ldclient.services.ldclient.LDClient;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.repository.RepositoryConnection;
+
+/**
+ * Test if the dummy components work.
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class DummyTest {
+
+ private LDClientService ldclient;
+
+
+ @Before
+ public void setupClient() {
+ ClientConfiguration config = new ClientConfiguration();
+ config.addEndpoint(new DummyEndpoint());
+
+ ldclient = new LDClient(config);
+ }
+
+ @After
+ public void shutdownClient() {
+ ldclient.shutdown();
+ }
+
+ @Test
+ public void testDummyProvider() throws Exception {
+ ClientResponse resp1 = ldclient.retrieveResource("http://remote/resource1");
+ RepositoryConnection con1 = resp1.getTriples().getConnection();
+ try {
+ con1.begin();
+ Assert.assertEquals(3, con1.size());
+ con1.commit();
+ } finally {
+ con1.close();
+ }
+
+ ClientResponse resp2 = ldclient.retrieveResource("http://remote/resource2");
+ RepositoryConnection con2 = resp2.getTriples().getConnection();
+ try {
+ con2.begin();
+ Assert.assertEquals(2, con2.size());
+ con2.commit();
+ } finally {
+ con2.close();
+ }
+
+ ClientResponse resp3 = ldclient.retrieveResource("http://remote/resource3");
+ RepositoryConnection con3 = resp3.getTriples().getConnection();
+ try {
+ con3.begin();
+ Assert.assertEquals(2, con3.size());
+ con3.commit();
+ } finally {
+ con3.close();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/resources/META-INF/services/org.apache.marmotta.ldclient.api.provider.DataProvider
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/resources/META-INF/services/org.apache.marmotta.ldclient.api.provider.DataProvider b/ldcache/ldcache-sail-kiwi/src/test/resources/META-INF/services/org.apache.marmotta.ldclient.api.provider.DataProvider
new file mode 100644
index 0000000..d9367d2
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/resources/META-INF/services/org.apache.marmotta.ldclient.api.provider.DataProvider
@@ -0,0 +1 @@
+org.apache.marmotta.ldcache.sail.test.dummy.DummyProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource1.ttl
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource1.ttl b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource1.ttl
new file mode 100644
index 0000000..bc34cc1
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource1.ttl
@@ -0,0 +1,4 @@
+@prefix ex: <http://remote/> .
+ex:resource1 ex:property1 "Value 1" ;
+ ex:property2 ex:resource2 ;
+ ex:property3 "Value X" .
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource2.ttl
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource2.ttl b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource2.ttl
new file mode 100644
index 0000000..1e02b0b
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource2.ttl
@@ -0,0 +1,3 @@
+@prefix ex: <http://remote/> .
+ex:resource2 ex:property1 "Value 2" ;
+ ex:property2 ex:resource3 .
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource3.ttl
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource3.ttl b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource3.ttl
new file mode 100644
index 0000000..0964311
--- /dev/null
+++ b/ldcache/ldcache-sail-kiwi/src/test/resources/org/apache/marmotta/ldcache/sail/test/dummy/resource3.ttl
@@ -0,0 +1,3 @@
+@prefix ex: <http://remote/> .
+ex:resource3 ex:property1 "Value 3" ;
+ ex:property3 "Value 4" .
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail/.classpath
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail/.classpath b/ldcache/ldcache-sail/.classpath
new file mode 100644
index 0000000..90df7da
--- /dev/null
+++ b/ldcache/ldcache-sail/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail/.project
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail/.project b/ldcache/ldcache-sail/.project
new file mode 100644
index 0000000..09d5094
--- /dev/null
+++ b/ldcache/ldcache-sail/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldcache-sail</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail/.settings/org.eclipse.jdt.core.prefs b/ldcache/ldcache-sail/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..60105c1
--- /dev/null
+++ b/ldcache/ldcache-sail/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-sail/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-sail/.settings/org.eclipse.m2e.core.prefs b/ldcache/ldcache-sail/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldcache/ldcache-sail/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/pom.xml
----------------------------------------------------------------------
diff --git a/ldcache/pom.xml b/ldcache/pom.xml
new file mode 100644
index 0000000..6e1b3e9
--- /dev/null
+++ b/ldcache/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2013 The Apache Software Foundation
+ ~
+ ~ Licensed 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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>lmf-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-parent</artifactId>
+ <name>LDCache: Parent</name>
+ <packaging>pom</packaging>
+
+ <description>
+ Linked Data Caching: Parent POM
+ </description>
+
+ <developers>
+ <developer>
+ <name>Sebastian Schaffert</name>
+ <email>sschaffert@apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Jakob Frank</name>
+ <email>jfrank@apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ </developers>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin> <!-- generate JRebel Configuration -->
+ <groupId>org.zeroturnaround</groupId>
+ <artifactId>jrebel-maven-plugin</artifactId>
+ <configuration>
+ <relativePath>../../</relativePath>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <modules>
+ <module>ldcache-api</module>
+ <module>ldcache-core</module>
+ <module>ldcache-sail-kiwi</module>
+ <module>ldcache-sail-generic</module>
+ <module>ldcache-backend-ehcache</module>
+ <module>ldcache-backend-kiwi</module>
+ <!--
+ <module>ldcache-backend-ehcache</module>
+ <module>ldcache-backend-kiwi</module>
+ -->
+ </modules>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/.project
----------------------------------------------------------------------
diff --git a/ldclient/.project b/ldclient/.project
new file mode 100644
index 0000000..72be855
--- /dev/null
+++ b/ldclient/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldclient-parent</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldclient/.settings/org.eclipse.m2e.core.prefs b/ldclient/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldclient/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/README.txt
----------------------------------------------------------------------
diff --git a/ldclient/README.txt b/ldclient/README.txt
new file mode 100644
index 0000000..2cc03a5
--- /dev/null
+++ b/ldclient/README.txt
@@ -0,0 +1,12 @@
+This component will contain all the code necessary for accessing linked data resources. It will be split into the
+following modules:
+
+- ldclient-api: defines the API for accessing LD resources, as well as the model for data providers that wrap
+ legacy sources
+- ldclient-core: implements the core functionality for accessing LD resources via HTTP and other protocols; offers
+ access to the API through a factory
+- ldclient-provider-rdf: implements providers for accessing LD resources that already offer data as RDF
+- ldclient-provider-xml: implements (abstract) providers for accessing LD resources that offer some form of XML;
+ these providers can be subclassed for mapping XPath expressions to RDF properties
+
+In addition, a number of custom providers can be defined.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.classpath
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.classpath b/ldclient/ldclient-api/.classpath
new file mode 100644
index 0000000..1b28ee5
--- /dev/null
+++ b/ldclient/ldclient-api/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="org.eclipse.jst.component.nondependency" value=""/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.project
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.project b/ldclient/ldclient-api/.project
new file mode 100644
index 0000000..57ebe04
--- /dev/null
+++ b/ldclient/ldclient-api/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldclient-api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.settings/org.eclipse.core.resources.prefs b/ldclient/ldclient-api/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..2b76340
--- /dev/null
+++ b/ldclient/ldclient-api/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.settings/org.eclipse.jdt.core.prefs b/ldclient/ldclient-api/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..69c31cd
--- /dev/null
+++ b/ldclient/ldclient-api/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.settings/org.eclipse.m2e.core.prefs b/ldclient/ldclient-api/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldclient/ldclient-api/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.settings/org.eclipse.wst.common.component
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.settings/org.eclipse.wst.common.component b/ldclient/ldclient-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..56ef980
--- /dev/null
+++ b/ldclient/ldclient-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="ldclient-api">
+ <wb-resource deploy-path="/" source-path="/src/main/java"/>
+ </wb-module>
+</project-modules>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/.settings/org.eclipse.wst.common.project.facet.core.xml
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/ldclient/ldclient-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..c78d932
--- /dev/null
+++ b/ldclient/ldclient-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="java" version="1.6"/>
+ <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/pom.xml
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/pom.xml b/ldclient/ldclient-api/pom.xml
new file mode 100644
index 0000000..7a42fc4
--- /dev/null
+++ b/ldclient/ldclient-api/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2013 Salzburg Research.
+ ~
+ ~ Licensed 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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldclient-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <artifactId>ldclient-api</artifactId>
+ <name>LDClient: API</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>marmotta-commons</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-repository-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-repository-sail</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-repository-event</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-sail-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-sail-memory</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/endpoint/Endpoint.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/endpoint/Endpoint.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/endpoint/Endpoint.java
new file mode 100644
index 0000000..21ddb93
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/endpoint/Endpoint.java
@@ -0,0 +1,311 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.api.endpoint;
+
+import org.apache.marmotta.commons.http.ContentType;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import static org.apache.marmotta.commons.http.LMFHttpUtils.parseAcceptHeader;
+
+/**
+ * Definition of a Linked Data Endpoint. Contains information how to query the
+ * endpoint, what format to expect, and when to expire data from this endpoint.
+ * <p/>
+ * <ul>
+ * <li> LinkedDataProvider endpoints will be accessed by directly
+ * retrieving the URI with appropriate Accept headers following the Linked Data
+ * recommendations
+ * <li> CacheProvider endpoints will be accessed by passing the URI
+ * as request parameter to the cache and parsing the response according to the
+ * content type defined for this endpoint (Content-Type header is too
+ * unspecific)
+ * <li> SPARQLProvider endpoints will be accessed by issuing a query
+ * of <code>SELECT ?p ?o WHERE { {url} ?p ?o }</code> to retrieve all triples
+ * for the requested resource
+ * <li> NONE act as blacklist. Resources matching handled by this endpoint are not fetched.
+ * </ul>
+ * <p/>
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ * <p/>
+ * User: sschaffe
+ */
+public class Endpoint implements Comparable<Endpoint> {
+
+ /**
+ * constant indicating high priority of this endpoint definition
+ */
+ public final static int PRIORITY_HIGH = 3;
+
+ /**
+ * constant indicating medium priority of this endpoint definition
+ */
+ public final static int PRIORITY_MEDIUM = 2;
+
+ /**
+ * constant indicating low priority of this endpoint definition
+ */
+ public final static int PRIORITY_LOW = 1;
+
+ /**
+ * A human-readable name for this endpoint.
+ */
+ private String name;
+
+ /**
+ * The type of the endpoint. Either the name of a data provider, or the special name "NONE" to indicate that
+ * the data for these URIs should not be retrieved.
+ */
+ private String type;
+
+
+ public static final String REGEX_INDICATOR = "~";
+
+ /**
+ * A regular expression describing for which URIs the endpoint applies. The endpoint will be applied to all
+ * resource requests matching with this pattern.
+ *
+ * @see Pattern
+ */
+ private String uriPattern;
+
+ private Pattern uriPatternCompiled = null;
+
+ /**
+ * Flag to temporarily enable/disable the endpoint configuration at runtime.
+ */
+ private boolean active;
+
+ /**
+ * The priority of this endpoint configuration; endpoints with higher priority take precedence over
+ * endpoints with lower priority in case both would be applicable.
+ */
+ private int priority = PRIORITY_MEDIUM;
+
+ /**
+ * The HTTP URL to access the endpoint. Occurrences of the string {uri} will
+ * be replaced by the resource URI of the queried resource for CACHE
+ * endpoints. Occurrences of the string {query} will be replaced by the
+ * SPARQL query for the requested resource for SPARQL endpoints.
+ *
+ * Requried for SPARQL and CACHE endpoints, ignored for LINKEDDATA endpoints
+ *
+ * <pre>
+ * Examples:
+ * - Sindice: http://api.sindice.com/v2/live?url={uri}
+ * or http://api.sindice.com/v2/cache?url={uri}
+ * or http://sparql.sindice.com/sparql?default-graph-uri=&query={query}&format=text%2Fhtml&debug=on
+ * - Stanbol: http://dev.iks-project.eu:8080/entityhub/lookup/?id={uri}&create=false
+ * </pre>
+ */
+ private String endpointUrl;
+
+
+ /**
+ * The content type (MIME) returned by this endpoint. Used to determine how to parse the result.
+ */
+ private Set<ContentType> contentTypes;
+
+ /**
+ * The default expiry time in seconds to use for this endpoint if the HTTP request does not explicitly return an
+ * expiry time.
+ */
+ private Long defaultExpiry;
+
+
+ /**
+ * Additional configuration options used by this endpoint. Can be accessed in the different providers.
+ */
+ private Map<String,String> properties;
+
+ public Endpoint() {
+ }
+
+ public Endpoint(String name, String type, String uriPattern, String endpointUrl, Long defaultExpiry) {
+ this.name = name;
+ this.type = type;
+ this.uriPattern = uriPattern;
+ this.endpointUrl = endpointUrl;
+ this.contentTypes = new HashSet<ContentType>();
+ this.defaultExpiry = defaultExpiry;
+ this.active = true;
+ this.properties = new HashMap<String, String>();
+ }
+
+ public Endpoint(String name, String type, String uriPattern, String endpointUrl, String contentType, Long defaultExpiry) {
+ this(name,type,uriPattern,endpointUrl,defaultExpiry);
+ this.contentTypes = new HashSet<ContentType>(parseAcceptHeader(contentType));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getUriPattern() {
+ return uriPattern;
+ }
+
+ public void setUriPattern(String uriPattern) {
+ this.uriPattern = uriPattern;
+ this.uriPatternCompiled = null;
+ }
+
+ public String getEndpointUrl() {
+ return endpointUrl;
+ }
+
+ public void setEndpointUrl(String endpointUrl) {
+ this.endpointUrl = endpointUrl;
+ }
+
+ public Set<ContentType> getContentTypes() {
+ return contentTypes;
+ }
+
+ public void addContentType(ContentType type) {
+ contentTypes.add(type);
+ }
+
+ public void setContentTypes(Set<ContentType> contentTypes) {
+ this.contentTypes = contentTypes;
+ }
+
+ public Long getDefaultExpiry() {
+ return defaultExpiry;
+ }
+
+ public void setDefaultExpiry(Long defaultExpiry) {
+ this.defaultExpiry = defaultExpiry;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+
+ public String getProperty(String key) {
+ return properties.get(key);
+ }
+
+ public void setProperty(String key, String value) {
+ properties.put(key,value);
+ }
+
+
+ public Pattern getUriPatternCompiled() {
+ if (uriPatternCompiled == null) {
+ try {
+ if (uriPattern.startsWith(REGEX_INDICATOR)) {
+ // backwards compatibility
+ uriPatternCompiled = Pattern.compile(uriPattern.substring(REGEX_INDICATOR.length()));
+ } else {
+ uriPatternCompiled = Pattern.compile(uriPattern);
+ }
+ } catch (PatternSyntaxException pse) {
+ }
+ }
+ return uriPatternCompiled;
+ }
+
+ /**
+ * Check if this {@link Endpoint} handles (is responsible) for this URI.
+ *
+ * @param uri the URI to check
+ * @return <code>true</code> if the uri matches the endpoint's {@link #uriPattern}
+ *
+ * @see #uriPattern
+ */
+ public boolean handles(String uri) {
+ if (isActive() && getUriPatternCompiled() != null) return getUriPatternCompiled().matcher(uri).find();
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Endpoint endpoint = (Endpoint) o;
+
+ if (name != null ? !name.equals(endpoint.name) : endpoint.name != null) return false;
+ if (type != null ? !type.equals(endpoint.type) : endpoint.type != null) return false;
+ if (uriPattern != null ? !uriPattern.equals(endpoint.uriPattern) : endpoint.uriPattern != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (type != null ? type.hashCode() : 0);
+ result = 31 * result + (uriPattern != null ? uriPattern.hashCode() : 0);
+ return result;
+ }
+
+
+ /**
+ * Compares this object with the specified object for order according to priority.
+ * Returns a negative integer, zero, or a positive integer as this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * @see #getPriority()
+ * @param o the object to be compared.
+ * @return a negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ * @throws NullPointerException if the specified object is null
+ * @throws ClassCastException if the specified object's type prevents it
+ * from being compared to this object.
+ */
+ @Override
+ public int compareTo(Endpoint o) {
+ if(getPriority() > o.getPriority()) {
+ return -1;
+ } else if(getPriority() < o.getPriority()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/ldclient/LDClientService.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/ldclient/LDClientService.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/ldclient/LDClientService.java
new file mode 100644
index 0000000..64572ac
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/ldclient/LDClientService.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.api.ldclient;
+
+import org.apache.http.client.HttpClient;
+import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
+import org.apache.marmotta.ldclient.api.provider.DataProvider;
+import org.apache.marmotta.ldclient.exception.DataRetrievalException;
+import org.apache.marmotta.ldclient.model.ClientConfiguration;
+import org.apache.marmotta.ldclient.model.ClientResponse;
+
+import java.util.Set;
+
+/**
+ * A service offering Linked Data client functionality for retrieving Linked Data resources from the cloud.
+ * Implements retrieval of triples from the cloud depending on the Endpoint definitions available for a resource.
+ *
+ * <p/>
+ * User: Sebastian Schaffert
+ */
+public interface LDClientService {
+
+ /**
+ * Perform a ping (HTTP HEAD) to the resource
+ *
+ * @param resource
+ * @return
+ */
+ public boolean ping(String resource);
+
+ /**
+ * Retrieve all triples for this resource from the Linked Data Cloud. Retrieval will be carried out according
+ * to the endpoint definition that matches this resource. In case no endpoint definition is found, the method
+ * will try an "default" Linked Data retrieval if the configuration option "ldcache.fallback" is set to true
+ *
+ *
+ *
+ * @param resource the URI resource for which to retrieve the triples
+ * @return a Sesame in-memory repository containing the triples for this resource
+ */
+ public ClientResponse retrieveResource(String resource) throws DataRetrievalException;
+
+ /**
+ * Get access to the Apache HTTP Client managed by the connection handler to execute
+ * a request.
+ *
+ * @return
+ */
+ public HttpClient getClient();
+
+
+ /**
+ * Get the client configuration used by the connection handler
+ * @return
+ */
+ public ClientConfiguration getClientConfiguration();
+
+ /**
+ * Retrieve the endpoint matching the KiWiUriResource passed as argument. The endpoint is determined by
+ * matching the endpoint's URI prefix with the resource URI. If no matching endpoint exists, returns null.
+ * The LinkedDataClientService can then decide (based on configuration) whether to try with a standard
+ * LinkedDataRequest or ignore the request.
+ *
+ * @param resource the KiWiUriResource to check.
+ */
+ Endpoint getEndpoint(String resource);
+
+ /**
+ * Test whether an endpoint definition for the given url pattern already exists.
+ *
+ * @param urlPattern
+ * @return
+ */
+ boolean hasEndpoint(String urlPattern);
+
+ void shutdown();
+
+ /**
+ * Return a collection of all available data providers (i.e. registered through the service loader).
+ * @return
+ */
+ Set<DataProvider> getDataProviders();
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/DataProvider.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/DataProvider.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/DataProvider.java
new file mode 100644
index 0000000..6359961
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/DataProvider.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.api.provider;
+
+import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
+import org.apache.marmotta.ldclient.api.ldclient.LDClientService;
+import org.apache.marmotta.ldclient.exception.DataRetrievalException;
+import org.apache.marmotta.ldclient.model.ClientResponse;
+
+/**
+ * Abstract interface for defining different implementations of data providers. Standard data
+ * providers are Linked Data and SPARQL, but in principle any data source can be wrapped as RDF
+ * (e.g. Google Data API)
+ * <p/>
+ * Data provider should be implemented as CDI service beans and can make use of @PostConstruct
+ * methods for registering themselves for specific URIs or carrying out maintenance work.
+ *
+ * @author Sebastian Schaffert
+ */
+public interface DataProvider {
+
+ /**
+ * Return the name of this data provider. To be used e.g. in the configuration and in log messages.
+ * @return
+ */
+ public String getName();
+
+
+ /**
+ * Return the list of mime types accepted by this data provider.
+ *
+ * @return
+ */
+ public String[] listMimeTypes();
+
+ /**
+ * Retrieve the data for a resource using the given http client and endpoint definition. The service is
+ * supposed to manage the connection handling itself. See AbstractHttpProvider
+ * for a generic implementation of this method.
+ *
+ *
+ *
+ * @param resource the resource to be retrieved
+ * @param endpoint the endpoint definition
+ * @return a completely specified client response, including expiry information and the set of triples
+ */
+ public ClientResponse retrieveResource(String resource, LDClientService client, Endpoint endpoint) throws DataRetrievalException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/ValueMapper.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/ValueMapper.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/ValueMapper.java
new file mode 100644
index 0000000..6ac35e1
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/api/provider/ValueMapper.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.api.provider;
+
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+
+import java.util.List;
+
+/**
+ * Map the value returned by a selection in a different data format (e.g. an XPath expression( into a list of Sesame
+ * values, using the ValueFactory passed as argument.
+ *
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public interface ValueMapper {
+
+ /**
+ * Take the selected value, process it according to the mapping definition, and create Sesame Values using the
+ * factory passed as argument.
+ *
+ *
+ * @param resourceUri
+ * @param selectedValue
+ * @param factory
+ * @return
+ */
+ public List<Value> map(String resourceUri, String selectedValue, ValueFactory factory);
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/exception/DataRetrievalException.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/exception/DataRetrievalException.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/exception/DataRetrievalException.java
new file mode 100644
index 0000000..1753854
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/exception/DataRetrievalException.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.exception;
+
+/**
+ * Thrown in case an error occurs during data import or retrieval.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class DataRetrievalException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with <code>null</code> as its detail message.
+ * The cause is not initialized, and may subsequently be initialized by a
+ * call to {@link #initCause}.
+ */
+ public DataRetrievalException() {
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message. The
+ * cause is not initialized, and may subsequently be initialized by
+ * a call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public DataRetrievalException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * <code>cause</code> is <i>not</i> automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DataRetrievalException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail
+ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+ * typically contains the class and detail message of <tt>cause</tt>).
+ * This constructor is useful for exceptions that are little more than
+ * wrappers for other throwables (for example, {@link
+ * java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public DataRetrievalException(Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientConfiguration.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientConfiguration.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientConfiguration.java
new file mode 100644
index 0000000..52b7819
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientConfiguration.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.model;
+
+import org.apache.http.client.HttpClient;
+import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Configuration options for the Linked Data Client.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class ClientConfiguration {
+
+ /**
+ * Socket timeout in milliseconds; maximum time a socket may be idle; default 60 seconds
+ */
+ private int socketTimeout = 60000;
+
+ /**
+ * HTTP connection timeout in milliseconds; default 10 seconds, because we don't want slow servers to slow down
+ * batch retrievals
+ */
+ private int connectionTimeout = 10000;
+
+ /**
+ * Maximum number of HTTP requests to run in parallel
+ */
+ private int maxParallelRequests = 10;
+
+
+ /**
+ * Default expiry time in seconds if not given by the server.
+ */
+ private long defaultExpiry = 86400;
+
+ /**
+ * Minimum expiry time in seconds in case the server returns a lower expiry time
+ */
+ private long minimumExpiry = 30;
+
+ /**
+ * The URI prefixes to exclude from retrieval; this is typically used for resources that are
+ * considered "local", i.e. managed by the local triple store
+ */
+ private Set<String> excludeUris;
+
+ /**
+ * A collection of endpoint definitions to use by this Linked Data Client.
+ */
+ private Set<Endpoint> endpoints;
+
+ /**
+ * A HttpClient used for retrieving the resource data.
+ */
+ private HttpClient httpClient;
+
+ public ClientConfiguration() {
+ excludeUris = new HashSet<String>();
+ endpoints = new HashSet<Endpoint>();
+ httpClient = null;
+ }
+
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+
+ public int getMaxParallelRequests() {
+ return maxParallelRequests;
+ }
+
+ public void setMaxParallelRequests(int maxParallelRequests) {
+ this.maxParallelRequests = maxParallelRequests;
+ }
+
+
+ public long getDefaultExpiry() {
+ return defaultExpiry;
+ }
+
+ public void setDefaultExpiry(long defaultExpiry) {
+ this.defaultExpiry = defaultExpiry;
+ }
+
+ public long getMinimumExpiry() {
+ return minimumExpiry;
+ }
+
+ public void setMinimumExpiry(long minimumExpiry) {
+ this.minimumExpiry = minimumExpiry;
+ }
+
+ public void addExcludeUri(String uriPrefix) {
+ excludeUris.add(uriPrefix);
+ }
+
+ public Set<String> getExcludeUris() {
+ return excludeUris;
+ }
+
+ public void setExcludeUris(Set<String> excludeUris) {
+ this.excludeUris = excludeUris;
+ }
+
+ /**
+ * Return true in case the URI passed as argument is considered to be excluded.
+ *
+ * @param uri
+ * @return
+ */
+ public boolean isExcludedUri(String uri) {
+ for(String prefix : excludeUris) {
+ if(uri.startsWith(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ public void addEndpoint(Endpoint endpoint) {
+ endpoints.add(endpoint);
+ }
+
+ public Set<Endpoint> getEndpoints() {
+ return endpoints;
+ }
+
+ public void setEndpoints(Set<Endpoint> endpoints) {
+ this.endpoints = endpoints;
+ }
+
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ public void setHttpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientResponse.java
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientResponse.java b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientResponse.java
new file mode 100644
index 0000000..4811ade
--- /dev/null
+++ b/ldclient/ldclient-api/src/main/java/org/apache/marmotta/ldclient/model/ClientResponse.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.ldclient.model;
+
+import org.apache.commons.lang.time.DateUtils;
+import org.openrdf.repository.Repository;
+
+import java.util.Date;
+
+/**
+ * LDCache Client Response
+ *
+ * @author Sebastian Schaffert
+ * @author Sergio Fernández
+ */
+public class ClientResponse {
+
+ private static final int DEFAULT_EXPIRATION_IN_DAYS = 7;
+
+ private Repository triples;
+
+ private Date expires;
+
+ public ClientResponse(Repository triples) {
+ this.triples = triples;
+ this.expires = DateUtils.addDays(new Date(), DEFAULT_EXPIRATION_IN_DAYS);
+ }
+
+ public Repository getTriples() {
+ return triples;
+ }
+
+ public void setTriples(Repository triples) {
+ this.triples = triples;
+ }
+
+ public Date getExpires() {
+ return expires;
+ }
+
+ public void setExpires(Date expires) {
+ this.expires = new Date(expires.getTime());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-core/.classpath
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-core/.classpath b/ldclient/ldclient-core/.classpath
new file mode 100644
index 0000000..bf96ac0
--- /dev/null
+++ b/ldclient/ldclient-core/.classpath
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="org.eclipse.jst.component.nondependency" value=""/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-core/.project
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-core/.project b/ldclient/ldclient-core/.project
new file mode 100644
index 0000000..50a702b
--- /dev/null
+++ b/ldclient/ldclient-core/.project
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldclient-core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.zeroturnaround.eclipse.rebelXmlBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.zeroturnaround.eclipse.jrebelNature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldclient/ldclient-core/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/ldclient/ldclient-core/.settings/org.eclipse.core.resources.prefs b/ldclient/ldclient-core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..dc1b414
--- /dev/null
+++ b/ldclient/ldclient-core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8