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:57:40 UTC
[9/11] added missing module from the previous code importation
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDClient.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDClient.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDClient.java
new file mode 100644
index 0000000..28a5b14
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDClient.java
@@ -0,0 +1,490 @@
+/**
+ * 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 at.newmedialab.ldclient.service;
+
+import at.newmedialab.ldclient.exception.LDClientException;
+import at.newmedialab.ldclient.model.ClientResponse;
+import at.newmedialab.ldclient.model.Endpoint;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.params.ClientPNames;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.DefaultRedirectStrategy;
+import org.apache.http.impl.cookie.DateParseException;
+import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.openrdf.model.Resource;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.TupleQueryResultHandler;
+import org.openrdf.query.TupleQueryResultHandlerException;
+import org.openrdf.query.resultio.QueryResultIO;
+import org.openrdf.query.resultio.QueryResultParseException;
+import org.openrdf.query.resultio.TupleQueryResultFormat;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.event.InterceptingRepositoryConnection;
+import org.openrdf.repository.event.base.InterceptingRepositoryConnectionWrapper;
+import org.openrdf.repository.event.base.RepositoryConnectionInterceptorAdapter;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFParseException;
+import org.openrdf.rio.RDFParserRegistry;
+import org.openrdf.sail.memory.MemoryStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class LDClient {
+
+ private Logger log = LoggerFactory.getLogger(LDClient.class);
+
+
+ private HttpParams httpParams;
+
+ private LDEndpoints ldEndpoints;
+
+ private Configuration config;
+
+
+ public LDClient() {
+ log.info("Initialising Linked Data Client Service ...");
+
+ ldEndpoints = new LDEndpoints();
+ try {
+ config = new PropertiesConfiguration("ldclient.properties");
+ } catch (ConfigurationException e) {
+ log.warn("could not load configuration file ldclient.properties from current directory, home directory, or classpath");
+ }
+
+
+ httpParams = new BasicHttpParams();
+ httpParams.setParameter(CoreProtocolPNames.USER_AGENT, "Salzburg NewMediaLab Linked Data Client");
+
+ httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, config.getInt("so_timeout", 60000));
+ httpParams.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, config.getInt("connection_timeout", 10000));
+
+ httpParams.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS,true);
+ httpParams.setIntParameter(ClientPNames.MAX_REDIRECTS,3);
+ }
+
+
+
+
+ /**
+ * 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(URI resource) throws LDClientException {
+ HttpResponse response = null;
+ try {
+ Endpoint endpoint = ldEndpoints.getEndpoint(resource);
+
+ if(endpoint != null && endpoint.getType() == Endpoint.EndpointType.NONE) {
+ return null;
+ } else if(endpoint != null) {
+ response = retrieveFromEndpoint(resource,endpoint);
+ return parseResponse(resource,response,endpoint);
+ } else if(config.getBoolean("fallback",true)) {
+ response = retrieveFromLDEndpoint(resource,null);
+ return parseResponse(resource,response,endpoint);
+ }
+ } catch(TupleQueryResultHandlerException ex) {
+ log.error("repository error while trying to retrieve resource "+resource.stringValue(),ex);
+
+ throw new LDClientException("repository error while trying to retrieve resource "+resource.stringValue(),ex);
+ } catch(QueryResultParseException ex) {
+ log.error("SPARQL query result parsing error while trying to retrieve resource "+resource.stringValue(),ex);
+
+ throw new LDClientException("SPARQL query result parsing error while trying to retrieve resource "+resource.stringValue(),ex);
+ } catch(RDFParseException ex) {
+ log.error("RDF parsing error while trying to retrieve resource "+resource.stringValue(),ex);
+
+ throw new LDClientException("RDF parsing error while trying to retrieve resource "+resource.stringValue(),ex);
+ } catch(RepositoryException ex) {
+ log.error("repository error while trying to retrieve resource "+resource.stringValue(),ex);
+
+ throw new LDClientException("repository error while trying to retrieve resource "+resource.stringValue(),ex);
+ } catch(IOException ex) {
+ log.error("I/O error while trying to retrieve resource {}: {}",resource.stringValue(),ex.getMessage());
+
+ throw new LDClientException("I/O error while trying to retrieve resource "+resource.stringValue(),ex);
+ } finally {
+ }
+
+
+ return null;
+ }
+
+
+
+ private HttpResponse retrieveFromEndpoint(URI resource, Endpoint endpoint) throws IOException, LDClientException {
+ switch (endpoint.getType()) {
+ case SPARQL:
+ return retrieveFromSparqlEndpoint(resource, endpoint);
+ case CACHE:
+ return retrieveFromCacheEndpoint(resource,endpoint);
+ case LINKEDDATA:
+ return retrieveFromLDEndpoint(resource,endpoint);
+ default:
+ return null;
+ }
+ }
+
+
+
+ private HttpResponse retrieveFromCacheEndpoint(URI resource, Endpoint endpoint) throws IOException {
+ // TODO: use last-modified header
+
+ HttpClient httpClient = createClient();
+
+
+ String contentType = endpoint.getContentType();
+
+ HttpGet get = new HttpGet(endpoint.getEndpointUrl().replace("{uri}", URLEncoder.encode(resource.stringValue(), "UTF-8")));
+ get.setHeader("Accept",contentType);
+ get.setHeader("Accept-Language", "*"); // PoolParty compatibility
+
+ log.info("retrieving resource {} from cache endpoint; request URI is {}", resource.stringValue(), get.getURI());
+
+ return httpClient.execute(get);
+ }
+
+
+ private HttpResponse retrieveFromLDEndpoint(URI resource, Endpoint endpoint) throws IOException, LDClientException {
+ // TODO: use last-modified header
+
+ HttpClient httpClient = createClient();
+
+ String contentType = "application/rdf+xml, text/rdf+n3;q=0.8, text/turtle;q=0.6";
+ if(endpoint != null) {
+ contentType = endpoint.getContentType();
+ }
+
+
+ HttpGet get = new HttpGet(resource.stringValue());
+ get.setHeader("Accept", contentType);
+ get.setHeader("Accept-Language", "*"); // PoolParty compatibility
+
+ log.info("retrieving resource {} as Linked Data; request URI is {}",resource.stringValue(),get.getURI());
+
+
+ HttpResponse result = httpClient.execute(get);
+ if(result.getEntity() == null || RDFParserRegistry.getInstance().getFileFormatForMIMEType(result.getEntity().getContentType().getValue().split(";")[0]) == null) {
+ get.abort();
+ if(result.getEntity() != null) {
+ throw new LDClientException("invalid content returned by Linked Data resource "+resource.stringValue()+": "+result.getEntity().getContentType().getValue());
+ } else {
+ throw new LDClientException("no content returned by Linked Data resource "+resource.stringValue());
+ }
+ }
+
+ return result;
+ }
+
+
+ private HttpResponse retrieveFromSparqlEndpoint(URI resource, Endpoint endpoint) throws IOException, LDClientException {
+ String contentType = "application/sparql-results+xml";
+ if(endpoint.getContentType() != null) {
+ contentType = endpoint.getContentType();
+ }
+
+ String query = "SELECT ?p ?o WHERE { <{uri}> ?p ?o }";
+
+ String url = endpoint.getEndpointUrl()
+ .replace("{query}", URLEncoder.encode(query.replace("{uri}",resource.stringValue()),"UTF-8"))
+ .replace("{contenttype}", URLEncoder.encode(contentType,"UTF-8"));
+
+ HttpClient httpClient = createClient();
+
+ HttpGet get = new HttpGet(url);
+ get.setHeader("Accept",contentType);
+ get.setHeader("Accept-Language", "*"); // PoolParty compatibility
+
+ log.info("retrieving resource {} from SPARQL endpoint; request URI is {}", resource.stringValue(), get.getURI());
+
+ return httpClient.execute(get);
+ }
+
+
+ private ClientResponse parseResponse(URI resource, HttpResponse response, Endpoint endpoint) throws LDClientException, IOException, RepositoryException, RDFParseException, QueryResultParseException, TupleQueryResultHandlerException {
+
+ if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 400) {
+
+ HttpEntity entity = response.getEntity();
+
+ if(entity != null) {
+ String contentType = "application/rdf+xml";
+ long defaultExpires = config.getInt("expiry", 86400);
+ if(endpoint != null && endpoint.getContentType() != null) {
+ contentType = endpoint.getContentType();
+ } else if(endpoint != null && endpoint.getType() == Endpoint.EndpointType.SPARQL) {
+ contentType = "application/sparql-results+xml";
+ } else if(entity.getContentType() != null) {
+ contentType = entity.getContentType().getValue().split(";")[0];
+ }
+ if(endpoint != null && endpoint.getDefaultExpiry() != null) {
+ defaultExpires = endpoint.getDefaultExpiry();
+ }
+
+
+ InputStream in = entity.getContent();
+ try {
+ Repository triples;
+
+ if(endpoint != null) {
+ switch (endpoint.getType()) {
+ case SPARQL:
+ triples = parseSparqlResponse(resource,in,contentType);
+ break;
+ default:
+ triples = parseRDFResponse(resource,in,contentType);
+ }
+ } else {
+ triples = parseRDFResponse(resource,in,contentType);
+ }
+
+
+
+ ClientResponse result = new ClientResponse(triples);
+
+ Header expires = response.getFirstHeader("Expires");
+ if(expires != null) {
+ try {
+ Date expiresDate = DateUtils.parseDate(expires.getValue());
+ result.setExpires(expiresDate);
+ } catch (DateParseException e) {
+ log.warn("could not parse Expires: header, using default expiry settings");
+ Date expiresDate = new Date(System.currentTimeMillis()+defaultExpires*1000);
+ result.setExpires(expiresDate);
+ }
+ } else {
+ Date expiresDate = new Date(System.currentTimeMillis()+defaultExpires*1000);
+ result.setExpires(expiresDate);
+ }
+
+ if(log.isInfoEnabled()) {
+ RepositoryConnection con = triples.getConnection();
+ log.info("retrieved {} triples for resource {}; expiry date: {}",new Object[] {con.size(),resource.stringValue(),result.getExpires()});
+ con.close();
+ }
+
+ return result;
+ } finally {
+ in.close();
+ }
+ } else {
+ throw new IOException("the HTTP request did not contain any data");
+ }
+ } else {
+ log.error("the HTTP request failed (status: {})",response.getStatusLine());
+ throw new LDClientException("the HTTP request failed (status: "+response.getStatusLine()+")");
+ }
+
+ }
+
+
+
+ private Repository parseRDFResponse(final URI resource, InputStream in, String contentType) throws RepositoryException, IOException, RDFParseException {
+ RDFFormat format = RDFParserRegistry.getInstance().getFileFormatForMIMEType(contentType, RDFFormat.RDFXML);
+
+ Repository triples = new SailRepository(new MemoryStore());
+ triples.initialize();
+
+ InterceptingRepositoryConnection con =
+ new InterceptingRepositoryConnectionWrapper(triples,triples.getConnection());
+
+ con.addRepositoryConnectionInterceptor(new RepositoryConnectionInterceptorAdapter() {
+ @Override
+ public boolean add(RepositoryConnection conn, Resource s, org.openrdf.model.URI p, Value o, Resource... contexts) {
+ if(s instanceof org.openrdf.model.URI) {
+ // if s is a URI and subject a KiWiUriResource, return true if they are different
+ return !((org.openrdf.model.URI)s).stringValue().equals(resource.stringValue());
+ } else {
+ // in all other cases, return true to filter out the triple
+ return true;
+ }
+ };
+
+ @Override
+ public boolean remove(RepositoryConnection conn, Resource s, org.openrdf.model.URI p, Value o, Resource... contexts) {
+ if(s instanceof org.openrdf.model.URI) {
+ // if s is a URI and subject a KiWiUriResource, return true if they are different
+ return !((org.openrdf.model.URI)s).stringValue().equals(resource.stringValue());
+ } else {
+ // in all other cases, return true to filter out the triple
+ return true;
+ }
+ }
+ });
+
+
+
+ con.add(in,resource.stringValue(),format);
+ con.commit();
+ con.close();
+
+ return triples;
+
+ }
+
+
+
+ private Repository parseSparqlResponse(final URI resource, InputStream in, String contentType) throws RepositoryException, IOException, QueryResultParseException, TupleQueryResultHandlerException {
+ TupleQueryResultFormat format = QueryResultIO.getParserFormatForMIMEType(contentType, TupleQueryResultFormat.SPARQL);
+
+
+ final Repository triples = new SailRepository(new MemoryStore());
+ triples.initialize();
+
+ QueryResultIO.parse(in,format,
+ new TupleQueryResultHandler() {
+
+ RepositoryConnection con;
+ URI subject;
+
+ @Override
+ public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
+ subject = triples.getValueFactory().createURI(resource.stringValue());
+ try {
+ con = triples.getConnection();
+ } catch (RepositoryException e) {
+ throw new TupleQueryResultHandlerException("error while creating repository connection",e);
+ }
+ }
+
+ @Override
+ public void endQueryResult() throws TupleQueryResultHandlerException {
+ try {
+ con.commit();
+ con.close();
+ } catch (RepositoryException e) {
+ throw new TupleQueryResultHandlerException("error while closing repository connection",e);
+ }
+ }
+
+ @Override
+ public void handleSolution(BindingSet bindingSet) throws TupleQueryResultHandlerException {
+
+ try {
+ Value predicate = bindingSet.getValue("p");
+ Value object = bindingSet.getValue("o");
+
+ if(predicate instanceof URI) {
+ con.add(triples.getValueFactory().createStatement(subject,(URI)predicate,object));
+ } else {
+ log.error("ignoring binding as predicate {} is not a URI",predicate);
+ }
+ } catch (RepositoryException e) {
+ throw new TupleQueryResultHandlerException("error while adding triple to repository connection",e);
+ }
+ }
+ },
+ triples.getValueFactory());
+
+ return triples;
+
+
+ }
+
+
+ private HttpClient createClient() {
+ DefaultHttpClient client = new DefaultHttpClient(httpParams);
+ client.setRedirectStrategy(new LMFRedirectStrategy());
+ client.setHttpRequestRetryHandler(new LMFHttpRequestRetryHandler());
+ return client;
+ }
+
+
+ private class LMFRedirectStrategy extends DefaultRedirectStrategy {
+ @Override
+ public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
+ if (response == null) {
+ throw new IllegalArgumentException("HTTP response may not be null");
+ }
+
+ int statusCode = response.getStatusLine().getStatusCode();
+ String method = request.getRequestLine().getMethod();
+ Header locationHeader = response.getFirstHeader("location");
+ switch (statusCode) {
+ case HttpStatus.SC_MOVED_TEMPORARILY:
+ return (method.equalsIgnoreCase(HttpGet.METHOD_NAME)
+ || method.equalsIgnoreCase(HttpHead.METHOD_NAME)) && locationHeader != null;
+ case HttpStatus.SC_MOVED_PERMANENTLY:
+ case HttpStatus.SC_TEMPORARY_REDIRECT:
+ return method.equalsIgnoreCase(HttpGet.METHOD_NAME)
+ || method.equalsIgnoreCase(HttpHead.METHOD_NAME);
+ case HttpStatus.SC_SEE_OTHER:
+ return true;
+ case HttpStatus.SC_MULTIPLE_CHOICES:
+ return true;
+ default:
+ return false;
+ } //end of switch
+ }
+ }
+
+ private class LMFHttpRequestRetryHandler implements HttpRequestRetryHandler {
+ /**
+ * Determines if a method should be retried after an IOException
+ * occurs during execution.
+ *
+ * @param exception the exception that occurred
+ * @param executionCount the number of times this method has been
+ * unsuccessfully executed
+ * @param context the context for the request execution
+ * @return <code>true</code> if the method should be retried, <code>false</code>
+ * otherwise
+ */
+ @Override
+ public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
+ return false;
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDEndpoints.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDEndpoints.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDEndpoints.java
new file mode 100644
index 0000000..cecf005
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldclient/service/LDEndpoints.java
@@ -0,0 +1,91 @@
+/**
+ * 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 at.newmedialab.ldclient.service;
+
+import at.newmedialab.ldclient.model.Endpoint;
+import org.openrdf.model.URI;
+import org.slf4j.Logger;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class LDEndpoints {
+
+ private Logger log;
+
+
+ private List<Endpoint> endpoints;
+
+
+
+ public LDEndpoints() {
+ endpoints = new LinkedList<Endpoint>();
+ }
+
+
+ /**
+ * Add a new endpoint to the system. The endpoint will be persisted in the database.
+ *
+ * @param endpoint
+ */
+ public void addEndpoint(Endpoint endpoint) {
+ endpoints.add(endpoint);
+ }
+
+
+ /**
+ * List all endpoints registered in the system.
+ *
+ * @return a list of endpoints in the order they were added to the database.
+ */
+ public List<Endpoint> listEndpoints() {
+ return endpoints;
+ }
+
+ /**
+ * Remove the endpoint given as argument. The endpoint will be deleted in the database.
+ *
+ * @param endpoint
+ */
+ public void removeEndpoint(Endpoint endpoint) {
+ endpoints.remove(endpoint);
+ }
+
+
+ /**
+ * 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.
+ */
+ public Endpoint getEndpoint(URI resource) {
+ for(Endpoint endpoint : endpoints) {
+ if (endpoint.handles(resource)) {
+ return endpoint;
+ }
+ }
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/AbstractLDBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/AbstractLDBackend.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/AbstractLDBackend.java
new file mode 100644
index 0000000..372eb98
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/AbstractLDBackend.java
@@ -0,0 +1,177 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.linkeddata;
+
+import at.newmedialab.ldclient.api.LDCacheProvider;
+import at.newmedialab.ldclient.model.Endpoint;
+import at.newmedialab.ldclient.service.LDCache;
+import at.newmedialab.ldpath.backend.sesame.SesameRepositoryBackend;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.repository.Repository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Abstract superclass for Linked Data backends. Implements functionality common to all implementations.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public abstract class AbstractLDBackend extends SesameRepositoryBackend implements LDCacheProvider {
+
+ private Logger log = LoggerFactory.getLogger(AbstractLDBackend.class);
+
+ private LDCache ldCache;
+
+ /**
+ * Initialise a new sesame backend. Repository needs to be set using setRepository.
+ */
+ protected AbstractLDBackend() {
+ ldCache = new LDCache(this);
+
+ try {
+ Configuration config = new PropertiesConfiguration("endpoints.properties");
+
+ HashSet<String> endpointNames = new HashSet<String>();
+ for(Iterator<String> it = config.getKeys(); it.hasNext(); ) {
+ String key = it.next();
+ String[] components = key.split("\\.");
+ if(components.length > 1) {
+ endpointNames.add(components[0]);
+ }
+ }
+ for(String endpointName : endpointNames) {
+ String prefix = config.getString(endpointName+".prefix","");
+ String kind = config.getString(endpointName+".kind","");
+ String endpointUrl = config.getString(endpointName+".endpoint","");
+ String mimetype = config.getString(endpointName+".mimetype","");
+ long expiry = config.getLong(endpointName+".expiry",(long)86400);
+
+ Endpoint.EndpointType type;
+ try {
+ type = Endpoint.EndpointType.valueOf(kind.toUpperCase());
+ } catch (Exception e) {
+ type = Endpoint.EndpointType.LINKEDDATA;
+ }
+
+ if (prefix != null && prefix.startsWith(Endpoint.REGEX_INDICATOR)) {
+ // Check for valid Regex
+ try {
+ Pattern.compile(prefix.substring(Endpoint.REGEX_INDICATOR.length()));
+ } catch (PatternSyntaxException pse) {
+ log.error("invalid regexp pattern in endpoint '{}' prefix definition: {}",endpointName,prefix);
+ }
+ }
+ if (endpointUrl != null) {
+ endpointUrl = endpointUrl.replace('<', '{').replace('>', '}');
+ } else {
+ endpointUrl = "";
+ }
+ Endpoint endpoint = new Endpoint(endpointName, type, prefix, endpointUrl, mimetype, expiry);
+ log.info("Registering LD Cache Endpoint \"{}\"",endpointName);
+ registerEndpoint(endpoint);
+ }
+
+ } catch (ConfigurationException e) {
+ log.warn("could not load configuration file endpoints.properties from current directory, home directory, or classpath");
+ }
+
+
+ }
+
+ /**
+ * Return the sesame repository used for storing the triples that are retrieved from the Linked Data Cloud.
+ * Triples will always be added to the context http://www.newmedialab.at/ldclient/cache to be able to distinguish
+ * them from other triples.
+ *
+ * @return an initialised Sesame repository that can be used for caching triples
+ */
+ @Override
+ public Repository getTripleRepository() {
+ return getRepository();
+ }
+
+
+ /**
+ * List the objects of triples in the triple store underlying this backend that have the subject and
+ * property given as argument.
+ *
+ * @param subject the subject of the triples to look for
+ * @param property the property of the triples to look for
+ * @return all objects of triples with matching subject and property
+ */
+ @Override
+ public Collection<Value> listObjects(Value subject, Value property) {
+ if(isURI(subject)) {
+ ldCache.refreshResource((URI)subject);
+ }
+ return super.listObjects(subject, property);
+ }
+
+ /**
+ * List the subjects of triples in the triple store underlying this backend that have the object and
+ * property given as argument.
+ *
+ * @param object the object of the triples to look for
+ * @param property the property of the triples to look for
+ * @return all dubjects of triples with matching object and property
+ * @throws UnsupportedOperationException in case reverse selection is not supported (e.g. when querying Linked Data)
+ */
+ @Override
+ public Collection<Value> listSubjects(Value property, Value object) {
+ throw new IllegalArgumentException("reverse navigation not supported by Linked Data backend");
+ }
+
+
+ /**
+ * Register a new Linked Data endpoint with this cache provider.
+ *
+ * @param endpoint
+ */
+ @Override
+ public void registerEndpoint(Endpoint endpoint) {
+ ldCache.getEndpointService().addEndpoint(endpoint);
+ }
+
+ /**
+ * List all endpoints currently registered with the Linked Data cache provider.
+ *
+ * @return a collection of endpoints
+ */
+ @Override
+ public Collection<Endpoint> listEndpoints() {
+ return ldCache.getEndpointService().listEndpoints();
+ }
+
+ /**
+ * Unregister the Linked Data endpoint given as argument.
+ *
+ * @param endpoint the endpoint to unregister
+ */
+ @Override
+ public void unregisterEndpoint(Endpoint endpoint) {
+ ldCache.getEndpointService().removeEndpoint(endpoint);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDMemoryBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDMemoryBackend.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDMemoryBackend.java
new file mode 100644
index 0000000..adf2a0a
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDMemoryBackend.java
@@ -0,0 +1,70 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.linkeddata;
+
+import at.newmedialab.ldclient.model.CacheEntry;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.sail.memory.MemoryStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A Linked Data backend implementation with no persistent storage. All retrieved data is kept in memory and discarded
+ * when the virtual machine exits.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class LDMemoryBackend extends AbstractLDBackend {
+
+ private static final Logger log = LoggerFactory.getLogger(LDMemoryBackend.class);
+
+ private Map<String,CacheEntry> cacheEntries;
+
+ public LDMemoryBackend() {
+ super();
+
+ cacheEntries = new HashMap<String,CacheEntry>();
+
+ try {
+ Repository repository = new SailRepository(new MemoryStore());
+ repository.initialize();
+ setRepository(repository);
+
+ } catch (RepositoryException e) {
+ log.error("error initialising connection to Sesame in-memory repository",e);
+ }
+
+ }
+
+
+
+ /**
+ * Return a map that can be used to store caching metadata about resources. The LDCacheProvider should take care
+ * of persisting the metadata if desired.
+ *
+ * @return a map for storing caching metadata
+ */
+ @Override
+ public Map<String,CacheEntry> getMetadataRepository() {
+ return cacheEntries;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDPersistentBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDPersistentBackend.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDPersistentBackend.java
new file mode 100644
index 0000000..fdafd1e
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDPersistentBackend.java
@@ -0,0 +1,103 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.linkeddata;
+
+import at.newmedialab.ldclient.model.CacheEntry;
+import jdbm.RecordManager;
+import jdbm.RecordManagerFactory;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.sail.nativerdf.NativeStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * A Linked Data backend with persistent caching of the retrieved data. All data is read and stored in the directory
+ * passed as constructor argument.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class LDPersistentBackend extends AbstractLDBackend {
+ private static final Logger log = LoggerFactory.getLogger(LDMemoryBackend.class);
+
+ private Map<String,CacheEntry> cacheEntries;
+
+
+ private RecordManager recordManager;
+
+ /**
+ * Create a persistent linked data backend storing the cache data in the directory passed as argument.
+ * The directory will be created if it does not exist.
+ * @param dataDirectory
+ */
+ public LDPersistentBackend(File dataDirectory) throws IOException {
+ super();
+
+ if(!dataDirectory.exists()) {
+ dataDirectory.mkdirs();
+ }
+
+ File tripleStore = new File(dataDirectory.getAbsolutePath()+File.separator+"triples");
+ if(!tripleStore.exists()) {
+ tripleStore.mkdirs();
+ }
+
+
+ recordManager = RecordManagerFactory.createRecordManager(dataDirectory.getAbsolutePath()+File.separator+"resource_cache.cache");
+
+ cacheEntries = recordManager.treeMap("resources");
+
+ try {
+ Repository repository = new SailRepository(new NativeStore(tripleStore));
+ repository.initialize();
+ setRepository(repository);
+
+ } catch (RepositoryException e) {
+ log.error("error initialising connection to Sesame in-memory repository",e);
+ }
+ }
+
+
+ public void shutdown() {
+ try {
+ recordManager.close();
+ getRepository().shutDown();
+ } catch (IOException e) {
+ log.error("error shutting down record manager for resource cache");
+ } catch (RepositoryException e) {
+ log.error("error shutting down repository for resource cache");
+ }
+ }
+
+
+ /**
+ /**
+ * Return a map that can be used to store caching metadata about resources. The LDCacheProvider should take care
+ * of persisting the metadata if desired.
+ *
+ * @return a map for storing caching metadata
+ */
+ @Override
+ public Map<String,CacheEntry> getMetadataRepository() {
+ return cacheEntries;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDQuery.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDQuery.java b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDQuery.java
new file mode 100644
index 0000000..caee246
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/java/at/newmedialab/ldpath/backend/linkeddata/LDQuery.java
@@ -0,0 +1,187 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.linkeddata;
+
+import at.newmedialab.ldpath.LDPath;
+import at.newmedialab.ldpath.backend.sesame.SesameRepositoryBackend;
+import at.newmedialab.ldpath.exception.LDPathParseException;
+import ch.qos.logback.classic.Level;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Value;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Command line application for querying input from files.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class LDQuery {
+
+ private static final Logger log = LoggerFactory.getLogger(LDQuery.class);
+
+ public static void main(String[] args) {
+ Options options = buildOptions();
+
+ CommandLineParser parser = new PosixParser();
+ try {
+ CommandLine cmd = parser.parse( options, args);
+
+ Level logLevel = Level.WARN;
+
+ if(cmd.hasOption("loglevel")) {
+ String logLevelName = cmd.getOptionValue("loglevel");
+ if("DEBUG".equals(logLevelName.toUpperCase())) {
+ logLevel = Level.DEBUG;
+ } else if("INFO".equals(logLevelName.toUpperCase())) {
+ logLevel = Level.INFO;
+ } else if("WARN".equals(logLevelName.toUpperCase())) {
+ logLevel = Level.WARN;
+ } else if("ERROR".equals(logLevelName.toUpperCase())) {
+ logLevel = Level.ERROR;
+ } else {
+ log.error("unsupported log level: {}",logLevelName);
+ }
+ }
+
+ if(logLevel != null) {
+ for(String logname : new String [] {"at","org","net","com"}) {
+
+ ch.qos.logback.classic.Logger logger =
+ (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(logname);
+ logger.setLevel(logLevel);
+ }
+ }
+
+
+ String format = null;
+ if(cmd.hasOption("format")) {
+ format = cmd.getOptionValue("format");
+ }
+
+ SesameRepositoryBackend backend;
+ if(cmd.hasOption("store")) {
+ backend = new LDPersistentBackend(new File(cmd.getOptionValue("store")));
+ } else {
+ backend = new LDMemoryBackend();
+ }
+
+ Resource context = null;
+ if(cmd.hasOption("context")) {
+ context = backend.getRepository().getValueFactory().createURI(cmd.getOptionValue("context"));
+ }
+
+ if(backend != null && context != null) {
+ LDPath<Value> ldpath = new LDPath<Value>(backend);
+
+ if(cmd.hasOption("path")) {
+ String path = cmd.getOptionValue("path");
+
+ for(Value v : ldpath.pathQuery(context,path,null)) {
+ System.out.println(v.stringValue());
+ }
+ } else if(cmd.hasOption("program")) {
+ File file = new File(cmd.getOptionValue("program"));
+
+ Map<String,Collection<?>> result = ldpath.programQuery(context,new FileReader(file));
+
+ for(String field : result.keySet()) {
+ StringBuilder line = new StringBuilder();
+ line.append(field);
+ line.append(" = ");
+ line.append("{");
+ for (Iterator<?> it = result.get(field).iterator(); it.hasNext();) {
+ line.append(it.next().toString());
+ if(it.hasNext()) {
+ line.append(", ");
+ }
+ }
+ line.append("}");
+ System.out.println(line);
+
+ }
+ }
+ }
+
+ if(backend instanceof LDPersistentBackend) {
+ ((LDPersistentBackend) backend).shutdown();
+ }
+
+
+ } catch (ParseException e) {
+ System.err.println("invalid arguments");
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp( "LDQuery", options, true );
+ } catch (LDPathParseException e) {
+ System.err.println("path or program could not be parsed");
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ System.err.println("file or program could not be found");
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("LDQuery", options, true);
+ } catch (IOException e) {
+ System.err.println("could not access cache data directory");
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("LDQuery", options, true);
+ }
+
+
+ }
+
+ @SuppressWarnings("static-access")
+ private static Options buildOptions() {
+ Options result = new Options();
+
+ OptionGroup query = new OptionGroup();
+ Option path = OptionBuilder.withArgName("path").hasArg().withDescription("LD Path to evaluate on the file starting from the context").create("path");
+ Option program = OptionBuilder.withArgName("file").hasArg().withDescription("LD Path program to evaluate on the file starting from the context").create("program");
+ query.addOption(path);
+ query.addOption(program);
+ query.setRequired(true);
+ result.addOptionGroup(query);
+
+ Option context = OptionBuilder.withArgName("uri").hasArg().withDescription("URI of the context node to start from").create("context");
+ context.setRequired(true);
+ result.addOption(context);
+
+ Option loglevel = OptionBuilder.withArgName("level").hasArg().withDescription("set the log level; default is 'warn'").create("loglevel");
+ result.addOption(loglevel);
+
+ Option store = OptionBuilder.withArgName("dir").hasArg().withDescription("cache the retrieved data in this directory").create("store");
+ result.addOption(store);
+
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/resources/endpoints.properties
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/resources/endpoints.properties b/ldpath/ldpath-backend-linkeddata/src/main/resources/endpoints.properties
new file mode 100644
index 0000000..154af30
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/resources/endpoints.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+# Blacklist Wikipedia
+wikipedia.prefix = ~http://(de\.|en\.|fr\.|es\.)?wikipedia\.org
+wikipedia.kind = NONE
+wikipedia.endpoint =
+wikipedia.mimetype =
+wikipedia.expiry = 86400
+
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-linkeddata/src/main/resources/ldclient.properties
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-linkeddata/src/main/resources/ldclient.properties b/ldpath/ldpath-backend-linkeddata/src/main/resources/ldclient.properties
new file mode 100644
index 0000000..f49bb77
--- /dev/null
+++ b/ldpath/ldpath-backend-linkeddata/src/main/resources/ldclient.properties
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+# how long to wait in ms when no data is sent over a connection
+so_timeout=60000
+
+# how long to wait in ms until a connection is established
+connection_timeout=10000
+
+# try to retrieve a resource using ordinary Linked Data call if no endpoint is specified
+fallback=true
+
+# default expiry time in seconds if not otherwise given (default: 1 day)
+expiry = 86400
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/.classpath
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.classpath b/ldpath/ldpath-backend-sesame/.classpath
new file mode 100644
index 0000000..1b28ee5
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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/32a909f7/ldpath/ldpath-backend-sesame/.project
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.project b/ldpath/ldpath-backend-sesame/.project
new file mode 100644
index 0000000..7552765
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldpath-backend-sesame</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.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</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/32a909f7/ldpath/ldpath-backend-sesame/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.settings/org.eclipse.core.resources.prefs b/ldpath/ldpath-backend-sesame/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..2b76340
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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/32a909f7/ldpath/ldpath-backend-sesame/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.settings/org.eclipse.jdt.core.prefs b/ldpath/ldpath-backend-sesame/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..69c31cd
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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/32a909f7/ldpath/ldpath-backend-sesame/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.settings/org.eclipse.m2e.core.prefs b/ldpath/ldpath-backend-sesame/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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/32a909f7/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.component
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.component b/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..319ccf7
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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="ldpath-backend-sesame">
+ <wb-resource deploy-path="/" source-path="/src/main/java"/>
+ </wb-module>
+</project-modules>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.project.facet.core.xml
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.project.facet.core.xml b/ldpath/ldpath-backend-sesame/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..c78d932
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/.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/32a909f7/ldpath/ldpath-backend-sesame/pom.xml
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/pom.xml b/ldpath/ldpath-backend-sesame/pom.xml
new file mode 100644
index 0000000..3fe8079
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/pom.xml
@@ -0,0 +1,54 @@
+<?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.ldpath</groupId>
+ <artifactId>ldpath-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <name>LDPath Backend: Sesame</name>
+ <artifactId>ldpath-backend-sesame</artifactId>
+ <packaging>jar</packaging>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>at.newmedialab.ldpath</groupId>
+ <artifactId>ldpath-api</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>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/AbstractSesameBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/AbstractSesameBackend.java b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/AbstractSesameBackend.java
new file mode 100644
index 0000000..deafa26
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/AbstractSesameBackend.java
@@ -0,0 +1,324 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.sesame;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.openrdf.model.BNode;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.newmedialab.ldpath.api.backend.RDFBackend;
+
+public abstract class AbstractSesameBackend implements RDFBackend<Value> {
+
+ private static final Logger log = LoggerFactory.getLogger(AbstractSesameBackend.class);
+
+ /**
+ * Return true if the underlying backend supports the parallel execution of queries.
+ *
+ * @return
+ */
+ @Override
+ public boolean supportsThreading() {
+ return false;
+ }
+
+ /**
+ * In case the backend supports threading, this method should return the ExecutorService representing the
+ * thread pool. LDPath lets the backend manage the thread pool to avoid excessive threading.
+ *
+ * @return
+ */
+ @Override
+ public ThreadPoolExecutor getThreadPool() {
+ return null;
+ }
+
+ /**
+ * Test whether the node passed as argument is a literal
+ *
+ * @param n the node to check
+ * @return true if the node is a literal
+ */
+ @Override
+ public boolean isLiteral(Value n) {
+ return n instanceof Literal;
+ }
+
+ /**
+ * Test whether the node passed as argument is a URI
+ *
+ * @param n the node to check
+ * @return true if the node is a URI
+ */
+ @Override
+ public boolean isURI(Value n) {
+ return n instanceof org.openrdf.model.URI;
+ }
+
+ /**
+ * Test whether the node passed as argument is a blank node
+ *
+ * @param n the node to check
+ * @return true if the node is a blank node
+ */
+ @Override
+ public boolean isBlank(Value n) {
+ return n instanceof BNode;
+ }
+
+ /**
+ * Return the language of the literal node passed as argument.
+ *
+ * @param n the literal node for which to return the language
+ * @return a Locale representing the language of the literal, or null if the literal node has no language
+ * @throws IllegalArgumentException in case the node is no literal
+ */
+ @Override
+ public Locale getLiteralLanguage(Value n) {
+ try {
+ if(((Literal)n).getLanguage() != null) {
+ return new Locale( ((Literal)n).getLanguage() );
+ } else {
+ return null;
+ }
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+n.stringValue()+" is not a literal" +
+ "but of type "+debugType(n));
+ }
+ }
+
+ /**
+ * Return the URI of the type of the literal node passed as argument.
+ *
+ * @param n the literal node for which to return the typer
+ * @return a URI representing the type of the literal content, or null if the literal is untyped
+ * @throws IllegalArgumentException in case the node is no literal
+ */
+ @Override
+ public URI getLiteralType(Value n) {
+ try {
+ if(((Literal)n).getDatatype() != null) {
+ try {
+ return new URI(((Literal)n).getDatatype().stringValue());
+ } catch (URISyntaxException e) {
+ log.error("literal datatype was not a valid URI: {}",((Literal) n).getDatatype());
+ return null;
+ }
+ } else {
+ return null;
+ }
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+n.stringValue()+" is not a literal" +
+ "but of type "+debugType(n));
+ }
+ }
+
+ /**
+ * Return the string value of a node. For a literal, this will be the content, for a URI node it will be the
+ * URI itself, and for a blank node it will be the identifier of the node.
+ *
+ * @param value
+ * @return
+ */
+ @Override
+ public String stringValue(Value value) {
+ return value.stringValue();
+ }
+
+ @Override
+ public BigDecimal decimalValue(Value node) {
+ try {
+ return ((Literal)node).decimalValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public BigInteger integerValue(Value node) {
+ try {
+ return ((Literal)node).integerValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Boolean booleanValue(Value node) {
+ try {
+ return ((Literal)node).booleanValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Date dateTimeValue(Value node) {
+ try {
+ XMLGregorianCalendar cal = ((Literal)node).calendarValue();
+ //TODO: check if we need to deal with timezone and Local here
+ return cal.toGregorianCalendar().getTime();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Date dateValue(Value node) {
+ try {
+ XMLGregorianCalendar cal = ((Literal)node).calendarValue();
+ return new GregorianCalendar(cal.getYear(), cal.getMonth(), cal.getDay()).getTime();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Date timeValue(Value node) {
+ //TODO: Unless someone knwos how to create a Date that only has the time
+ // from a XMLGregorianCalendar
+ return dateTimeValue(node);
+ }
+
+ @Override
+ public Long longValue(Value node) {
+ try {
+ return ((Literal)node).longValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Double doubleValue(Value node) {
+ try {
+ return ((Literal)node).doubleValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Float floatValue(Value node) {
+ try {
+ return ((Literal)node).floatValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ @Override
+ public Integer intValue(Value node) {
+ try {
+ return ((Literal)node).intValue();
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Value "+node.stringValue()+" is not a literal" +
+ "but of type "+debugType(node));
+ }
+ }
+
+ protected Collection<Value> listObjectsInternal(RepositoryConnection connection, Resource subject, org.openrdf.model.URI property)
+ throws RepositoryException {
+ Set<Value> result = new HashSet<Value>();
+ RepositoryResult<Statement> qResult = connection.getStatements(subject, property, null, true);
+ try {
+ while(qResult.hasNext()) {
+ result.add(qResult.next().getObject());
+ }
+ } finally {
+ qResult.close();
+ }
+ return result;
+ }
+
+ protected Collection<Value> listSubjectsInternal(final RepositoryConnection connection, org.openrdf.model.URI property, Value object)
+ throws RepositoryException {
+ Set<Value> result = new HashSet<Value>();
+ RepositoryResult<Statement> qResult = connection.getStatements(null, property, object, true);
+ try {
+ while(qResult.hasNext()) {
+ result.add(qResult.next().getSubject());
+ }
+ } finally {
+ qResult.close();
+ }
+ return result;
+ }
+
+ protected Value createURIInternal(final ValueFactory valueFactory, String uri) {
+ return valueFactory.createURI(uri);
+ }
+
+ protected Value createLiteralInternal(final ValueFactory valueFactory, String content) {
+ log.debug("creating literal with content \"{}\"",content);
+ return valueFactory.createLiteral(content);
+ }
+
+ protected Value createLiteralInternal(final ValueFactory valueFactory, String content, Locale language, URI type) {
+ log.debug("creating literal with content \"{}\", language {}, datatype {}",new Object[]{content,language,type});
+ if(language == null && type == null) {
+ return valueFactory.createLiteral(content);
+ } else if(type == null) {
+ return valueFactory.createLiteral(content,language.getLanguage());
+ } else {
+ return valueFactory.createLiteral(content, valueFactory.createURI(type.toString()));
+ }
+ }
+
+ /**
+ * Prints the type (URI,bNode,literal) by inspecting the parsed {@link Value}
+ * to improve error messages and other loggings. In case of literals
+ * also the {@link #getLiteralType(Value) literal type} is printed
+ * @param value the value or <code>null</code>
+ * @return the type as string.
+ */
+ protected String debugType(Value value) {
+ return value == null ? "null":isURI(value)?"URI":isBlank(value)?"bNode":
+ "literal ("+getLiteralType(value)+")";
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameConnectionBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameConnectionBackend.java b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameConnectionBackend.java
new file mode 100644
index 0000000..a805594
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameConnectionBackend.java
@@ -0,0 +1,85 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.sesame;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Locale;
+
+import org.openrdf.model.Resource;
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+public class SesameConnectionBackend extends AbstractSesameBackend {
+
+ private final RepositoryConnection connection;
+ private final ValueFactory valueFactory;
+
+ public SesameConnectionBackend(RepositoryConnection connection) {
+ this.connection = connection;
+ valueFactory = connection.getValueFactory();
+ }
+
+ @Override
+ public Value createLiteral(String content) {
+ return createLiteralInternal(valueFactory, content);
+ }
+
+ @Override
+ public Value createLiteral(String content, Locale language, URI type) {
+ return createLiteralInternal(valueFactory, content, language, type);
+ }
+
+ @Override
+ public Value createURI(String uri) {
+ return createURIInternal(valueFactory, uri);
+ }
+
+ @Override
+ public Collection<Value> listObjects(Value subject, Value property) {
+ try {
+ return listObjectsInternal(connection, (Resource) subject, (org.openrdf.model.URI) property);
+ } catch (RepositoryException e) {
+ throw new RuntimeException(
+ "error while querying Sesame repository!", e);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(String.format(
+ "Subject needs to be a URI or blank node, property a URI node "
+ + "(types: [subject: %s, property: %s])",
+ debugType(subject), debugType(property)), e);
+ }
+ }
+
+ @Override
+ public Collection<Value> listSubjects(Value property, Value object) {
+ try {
+ return listSubjectsInternal(connection, (org.openrdf.model.URI) property, object);
+ } catch (RepositoryException e) {
+ throw new RuntimeException("error while querying Sesame repository!",e);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(String.format(
+ "Property needs to be a URI node (property type: %s)",
+ isURI(property)?"URI":isBlank(property)?"bNode":"literal"),e);
+ }
+ }
+
+ public static SesameConnectionBackend withConnection(RepositoryConnection connection) {
+ return new SesameConnectionBackend(connection);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameRepositoryBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameRepositoryBackend.java b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameRepositoryBackend.java
new file mode 100644
index 0000000..94eda72
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/SesameRepositoryBackend.java
@@ -0,0 +1,161 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.sesame;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Locale;
+
+import org.openrdf.model.Resource;
+import org.openrdf.model.Value;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+/**
+ * Generic implementation of a Sesame backend for LDPath. A Sesame repository is passed as argument to the
+ * constructor.
+ * <p/>
+ * Implementatins can either use this class directly or implement their own Sesame-based backend by subclassing
+ * and calling the super constructor.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class SesameRepositoryBackend extends AbstractSesameBackend {
+
+ private Repository repository;
+
+ /**
+ * Initialise a new sesame backend. Repository needs to be set using setRepository.
+ */
+ protected SesameRepositoryBackend() {
+ }
+
+ /**
+ * Initialise a new sesame backend using the repository passed as argument.
+ *
+ * @param repository
+ */
+ public SesameRepositoryBackend(Repository repository) {
+ this.repository = repository;
+ }
+
+ public Repository getRepository() {
+ return repository;
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+
+ /**
+ * Create a literal node with the content passed as argument
+ *
+ * @param content string content to represent inside the literal
+ * @return a literal node in using the model used by this backend
+ */
+ @Override
+ public Value createLiteral(String content) {
+ return createLiteralInternal(repository.getValueFactory(), content);
+ }
+
+
+ /**
+ * Create a literal node with the content passed as argument
+ *
+ * @param content string content to represent inside the literal
+ * @return a literal node in using the model used by this backend
+ */
+ @Override
+ public Value createLiteral(String content, Locale language, URI type) {
+ return createLiteralInternal(repository.getValueFactory(), content, language, type);
+ }
+
+
+ /**
+ * Create a URI mode with the URI passed as argument
+ *
+ * @param uri URI of the resource to create
+ * @return a URI node using the model used by this backend
+ */
+ @Override
+ public Value createURI(String uri) {
+ return createURIInternal(repository.getValueFactory(), uri);
+ }
+
+ /**
+ * List the objects of triples in the triple store underlying this backend that have the subject and
+ * property given as argument.
+ *
+ * @param subject the subject of the triples to look for
+ * @param property the property of the triples to look for
+ * @return all objects of triples with matching subject and property
+ */
+ @Override
+ public Collection<Value> listObjects(Value subject, Value property) {
+ try {
+ RepositoryConnection connection = repository.getConnection();
+
+ try {
+ connection.begin();
+ return listObjectsInternal(connection, (Resource) subject, (org.openrdf.model.URI) property);
+ } finally {
+ connection.commit();
+ connection.close();
+ }
+ } catch (RepositoryException e) {
+ throw new RuntimeException("error while querying Sesame repository!",e);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(String.format(
+ "Subject needs to be a URI or blank node, property a URI node " +
+ "(types: [subject: %s, property: %s])",
+ debugType(subject),debugType(property)),e);
+ }
+
+ }
+
+ /**
+ * List the subjects of triples in the triple store underlying this backend that have the object and
+ * property given as argument.
+ *
+ * @param object the object of the triples to look for
+ * @param property the property of the triples to look for
+ * @return all subjects of triples with matching object and property
+ * @throws UnsupportedOperationException in case reverse selection is not supported (e.g. when querying Linked Data)
+ */
+ @Override
+ public Collection<Value> listSubjects(Value property, Value object) {
+ try {
+ final RepositoryConnection connection = repository.getConnection();
+
+ try {
+ connection.begin();
+ return listSubjectsInternal(connection, (org.openrdf.model.URI) property, object);
+ } finally {
+ connection.commit();
+ connection.close();
+ }
+ } catch (RepositoryException e) {
+ throw new RuntimeException("error while querying Sesame repository!",e);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(String.format(
+ "Property needs to be a URI node (property type: %s)",
+ isURI(property)?"URI":isBlank(property)?"bNode":"literal"),e);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/ThreadingSesameBackend.java
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/ThreadingSesameBackend.java b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/ThreadingSesameBackend.java
new file mode 100644
index 0000000..952abbf
--- /dev/null
+++ b/ldpath/ldpath-backend-sesame/src/main/java/at/newmedialab/ldpath/backend/sesame/ThreadingSesameBackend.java
@@ -0,0 +1,78 @@
+/**
+ * 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 at.newmedialab.ldpath.backend.sesame;
+
+
+import org.openrdf.repository.Repository;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * A threading version of the sesame backend.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public class ThreadingSesameBackend extends SesameRepositoryBackend {
+
+ private ThreadPoolExecutor workers;
+
+ /**
+ * Initialise a new sesame backend. Repository needs to be set using setRepository.
+ */
+ protected ThreadingSesameBackend() {
+ workers = (ThreadPoolExecutor) Executors.newCachedThreadPool();
+ }
+
+ /**
+ * Initialise a new sesame backend using the repository passed as argument.
+ *
+ * @param repository
+ */
+ public ThreadingSesameBackend(Repository repository) {
+ super(repository);
+ workers = (ThreadPoolExecutor)Executors.newFixedThreadPool(4);
+ }
+
+ /**
+ * Return true if the underlying backend supports the parallel execution of queries.
+ *
+ * @return
+ */
+ @Override
+ public boolean supportsThreading() {
+ return true;
+ }
+
+ /**
+ * In case the backend supports threading, this method should return the ExecutorService representing the
+ * thread pool. LDPath lets the backend manage the thread pool to avoid excessive threading.
+ *
+ * @return
+ */
+ @Override
+ public ThreadPoolExecutor getThreadPool() {
+ return workers;
+ }
+
+ /**
+ * Shut down the thread pool
+ */
+ public void shutdown() {
+ workers.shutdownNow();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/.classpath
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.classpath b/ldpath/ldpath-core/.classpath
new file mode 100644
index 0000000..f05966c
--- /dev/null
+++ b/ldpath/ldpath-core/.classpath
@@ -0,0 +1,19 @@
+<?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="src" output="target/classes" path="target/generated-sources/javacc">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/.project
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.project b/ldpath/ldpath-core/.project
new file mode 100644
index 0000000..d68e41b
--- /dev/null
+++ b/ldpath/ldpath-core/.project
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldpath-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.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+ <nature>org.eclipse.pde.PluginNature</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/32a909f7/ldpath/ldpath-core/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.settings/org.eclipse.core.resources.prefs b/ldpath/ldpath-core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..dc1b414
--- /dev/null
+++ b/ldpath/ldpath-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
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/32a909f7/ldpath/ldpath-core/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.settings/org.eclipse.jdt.core.prefs b/ldpath/ldpath-core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..69c31cd
--- /dev/null
+++ b/ldpath/ldpath-core/.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/32a909f7/ldpath/ldpath-core/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.settings/org.eclipse.m2e.core.prefs b/ldpath/ldpath-core/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldpath/ldpath-core/.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/32a909f7/ldpath/ldpath-core/.settings/org.eclipse.pde.core.prefs
----------------------------------------------------------------------
diff --git a/ldpath/ldpath-core/.settings/org.eclipse.pde.core.prefs b/ldpath/ldpath-core/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..ba582c2
--- /dev/null
+++ b/ldpath/ldpath-core/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,2 @@
+BUNDLE_ROOT_PATH=target/classes
+eclipse.preferences.version=1