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 2014/02/24 16:14:02 UTC

[2/3] git commit: MARMOTTA-440: refactorized sesame stuff out of the web service

MARMOTTA-440: refactorized sesame stuff out of the web service


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

Branch: refs/heads/ldp
Commit: 3731c87dd9dbd1ff4a131946bf273b49cb04c88b
Parents: cb8dc9b
Author: Sergio Fernández <wi...@apache.org>
Authored: Mon Feb 24 16:02:43 2014 +0100
Committer: Sergio Fernández <wi...@apache.org>
Committed: Mon Feb 24 16:02:43 2014 +0100

----------------------------------------------------------------------
 .../marmotta/platform/ldp/api/LdpService.java   |  39 +++
 .../platform/ldp/services/LdpServiceImpl.java   | 233 ++++++++++++++++
 .../platform/ldp/webservices/LdpWebService.java | 265 +++----------------
 3 files changed, 306 insertions(+), 231 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/marmotta/blob/3731c87d/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
index 7d1576e..9a746da 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
@@ -1,9 +1,48 @@
 package org.apache.marmotta.platform.ldp.api;
 
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFParseException;
+
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
 /**
  *  LDP Service
  *
  *  @author Sergio Fernández
  */
 public interface LdpService {
+
+    boolean exists(String resource) throws RepositoryException;
+
+    boolean exists(URI resource) throws RepositoryException;
+
+    boolean addResource(InputStream stream, MediaType type, String container, String resource) throws RepositoryException, IOException, RDFParseException;
+
+    boolean addResource(InputStream stream, MediaType type, URI container, URI resource) throws RepositoryException, IOException, RDFParseException;
+
+    List<Statement> getStatements(String resource) throws RepositoryException;
+
+    List<Statement> getStatements(URI resource) throws RepositoryException;
+
+    void exportResource(OutputStream output, String resource, RDFFormat format) throws RepositoryException, RDFHandlerException;
+
+    void exportResource(OutputStream output, URI resouce, RDFFormat format) throws RepositoryException, RDFHandlerException;
+
+    EntityTag generateETag(String uri) throws RepositoryException;
+
+    EntityTag generateETag(URI uri) throws RepositoryException;
+
+    boolean deleteResource(URI resource) throws RepositoryException;
+
+    boolean deleteResource(String resource) throws RepositoryException;
+
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3731c87d/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
index ae62315..0cee089 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
@@ -17,14 +17,35 @@
  */
 package org.apache.marmotta.platform.ldp.services;
 
+import info.aduna.iteration.UnionIteration;
+import org.apache.marmotta.commons.vocabulary.DCTERMS;
+import org.apache.marmotta.commons.vocabulary.LDP;
 import org.apache.marmotta.platform.core.api.config.ConfigurationService;
 import org.apache.marmotta.platform.core.api.triplestore.SesameService;
 import org.apache.marmotta.platform.ldp.api.LdpService;
+import org.apache.marmotta.platform.ldp.util.LdpWebServiceUtils;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.model.vocabulary.RDF;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.rio.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.List;
 
 /**
  * LDP Service default implementation
@@ -42,4 +63,216 @@ public class LdpServiceImpl implements LdpService {
     @Inject
     private SesameService sesameService;
 
+    private URI buildURI(String resource) {
+        return ValueFactoryImpl.getInstance().createURI(resource);
+    }
+
+    @Override
+    public boolean exists(String resource) throws RepositoryException {
+        return exists(buildURI(resource));
+    }
+
+    @Override
+    public boolean exists(URI resource) throws RepositoryException {
+        final RepositoryConnection conn = sesameService.getConnection();
+        try {
+            conn.begin();
+            final URI ldpContext = conn.getValueFactory().createURI(LDP.NAMESPACE);
+            return conn.hasStatement(resource, RDF.TYPE, null, true, ldpContext);
+        } finally {
+            conn.commit();
+            conn.close();
+        }
+    }
+
+    @Override
+    public List<Statement> getStatements(String resource) throws RepositoryException {
+        return getStatements(buildURI(resource));
+    }
+
+    @Override
+    public List<Statement> getStatements(URI resource) throws RepositoryException {
+        final RepositoryConnection conn = sesameService.getConnection();
+        try {
+            URI ldp = conn.getValueFactory().createURI(LDP.NAMESPACE);
+            return conn.getStatements(resource, RDF.TYPE, null, false, ldp).asList(); //FIXME
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Override
+    public void exportResource(OutputStream output, String resource, RDFFormat format) throws RepositoryException, RDFHandlerException {
+        exportResource(output, buildURI(resource), format);
+    }
+
+    @Override
+    public void exportResource(OutputStream output, URI resource, RDFFormat format) throws RepositoryException, RDFHandlerException {
+        RepositoryConnection conn = sesameService.getConnection();
+        try {
+            conn.begin();
+            URI ldpContext = conn.getValueFactory().createURI(LDP.NAMESPACE);
+            // TODO: this should be a little more sophisticated...
+            // TODO: non-membership triples flag / Prefer-header
+            RDFWriter writer = Rio.createWriter(format, output);
+            UnionIteration<Statement, RepositoryException> union = new UnionIteration<>(
+                    conn.getStatements(null, null, null, false, resource),
+                    conn.getStatements(resource, null, null, false, ldpContext)
+            );
+            try {
+                LdpWebServiceUtils.exportIteration(writer, resource, union);
+            } finally {
+                union.close();
+            }
+            conn.commit();
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Override
+    public boolean addResource(InputStream stream, MediaType type, String container, String resource) throws RepositoryException, IOException, RDFParseException {
+        return addResource(stream, type, buildURI(container), buildURI(resource));
+    }
+
+    @Override
+    public boolean addResource(InputStream stream, MediaType type, URI container, URI resource) throws RepositoryException, IOException, RDFParseException {
+        final RepositoryConnection conn = sesameService.getConnection();
+        try {
+            final URI ldpContext = conn.getValueFactory().createURI(LDP.NAMESPACE);
+            conn.begin();
+
+            log.trace("Checking possible name clash for new resource <{}>", resource.stringValue());
+            if (conn.hasStatement(resource, null, null, false, ldpContext)) {
+                int i = 0;
+                final String base = resource.stringValue();
+                do {
+                    final String candidate = base + "-" + (++i);
+                    log.trace("<{}> already exists, trying <{}>", resource.stringValue(), candidate);
+                    resource = conn.getValueFactory().createURI(candidate);
+                } while (conn.hasStatement(resource, null, null, false, ldpContext));
+                log.debug("resolved name clash, new resource will be <{}>", resource.stringValue());
+            } else {
+                log.debug("no name clash for <{}>", resource);
+            }
+
+            log.debug("POST to <{}> will create new LDP-R <{}>", container, resource);
+
+            // Add container triples (Sec. 6.4.3)
+            // container and meta triples!
+
+            Literal now = conn.getValueFactory().createLiteral(new Date());
+
+            conn.add(container, RDF.TYPE, LDP.BasicContainer, ldpContext);
+            conn.add(container, LDP.contains, resource, ldpContext);
+            conn.remove(container, DCTERMS.modified, null, ldpContext);
+            conn.add(container, DCTERMS.modified, now, ldpContext);
+
+            conn.add(resource, RDF.TYPE, LDP.Resource, ldpContext);
+            conn.add(resource, DCTERMS.created, now, ldpContext);
+            conn.add(resource, DCTERMS.modified, now, ldpContext);
+
+            // LDP-BC for now!
+            conn.commit();
+
+            // Add the bodyContent
+            log.trace("Content ({}) for new resource <{}>", type, resource);
+            final RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(type.toString());
+            if (rdfFormat == null) {
+                log.debug("POST creates new LDP-BR with type {}", type);
+                log.warn("LDP-BR not (yet) supported!");
+                throw new UnsupportedRDFormatException("No available parser for " + type.toString());
+            } else {
+                log.debug("POST creates new LDP-RR, data provided as {}", rdfFormat.getName());
+                conn.begin();
+
+                // FIXME: We are (are we?) allowed to filter out server-managed properties here
+                conn.add(stream, resource.stringValue(), rdfFormat, resource);
+
+                conn.commit();
+                return true;
+            }
+        } catch (final Throwable t) {
+            if (conn.isActive()) {
+                conn.rollback();
+            }
+            throw t;
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Override
+    public EntityTag generateETag(String resource) throws RepositoryException {
+        return generateETag(buildURI(resource));
+    }
+
+    @Override
+    public EntityTag generateETag(URI uri) throws RepositoryException {
+        final RepositoryConnection conn = sesameService.getConnection();
+        final URI ldpContext = conn.getValueFactory().createURI(LDP.NAMESPACE);
+        final RepositoryResult<Statement> stmts = conn.getStatements(uri, DCTERMS.modified, null, true, ldpContext);
+        try {
+            // TODO: ETag is the last-modified date (explicitly managed) thus only weak.
+            Date latest = null;
+            while (stmts.hasNext()) {
+                Value o = stmts.next().getObject();
+                if (o instanceof Literal) {
+                    Date d = ((Literal)o).calendarValue().toGregorianCalendar().getTime();
+                    if (latest == null || d.after(latest)) {
+                        latest = d;
+                    }
+                }
+            }
+            if (latest != null) {
+                return new EntityTag(String.valueOf(latest.getTime()), true);
+            } else {
+                return null;
+            }
+        } finally {
+            stmts.close();
+        }
+    }
+
+    @Override
+    public boolean deleteResource(String resource) throws RepositoryException {
+        return deleteResource(buildURI(resource));
+    }
+
+    @Override
+    public boolean deleteResource(URI resource) throws RepositoryException {
+        final RepositoryConnection conn = sesameService.getConnection();
+        try {
+            conn.begin();
+
+            log.warn("NOT CHECKING EXISTENCE OF <{}>", resource);
+
+            URI ldpContext = conn.getValueFactory().createURI(LDP.NAMESPACE);
+            Literal now = conn.getValueFactory().createLiteral(new Date());
+
+            // Delete corresponding containment and membership triples (Sec. 6.6.1)
+            RepositoryResult<Statement> stmts = conn.getStatements(null, LDP.member, resource, false, ldpContext);
+            try {
+                while (stmts.hasNext()) {
+                    Statement st = stmts.next();
+                    conn.remove(st.getSubject(), DCTERMS.modified, null);
+                    conn.add(st.getSubject(), DCTERMS.modified, now);
+                    conn.remove(st);
+                }
+            } finally {
+                stmts.close();
+            }
+            // Delete the resource meta
+            conn.remove(resource, null, null, ldpContext);
+
+            // Delete the resource data
+            conn.clear(resource);
+
+            conn.commit();
+            return true;
+        } finally {
+            conn.close();
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3731c87d/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
index e5de78e..42e6aa3 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
@@ -17,24 +17,20 @@
  */
 package org.apache.marmotta.platform.ldp.webservices;
 
-import info.aduna.iteration.UnionIteration;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.marmotta.commons.vocabulary.DCTERMS;
 import org.apache.marmotta.commons.vocabulary.LDP;
 import org.apache.marmotta.platform.core.api.config.ConfigurationService;
-import org.apache.marmotta.platform.core.api.triplestore.SesameService;
 import org.apache.marmotta.platform.ldp.api.LdpService;
 import org.apache.marmotta.platform.ldp.util.EntityTagUtils;
 import org.apache.marmotta.platform.ldp.util.LdpWebServiceUtils;
-import org.openrdf.model.Literal;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
 import org.openrdf.model.Value;
-import org.openrdf.model.vocabulary.RDF;
-import org.openrdf.repository.RepositoryConnection;
 import org.openrdf.repository.RepositoryException;
-import org.openrdf.repository.RepositoryResult;
-import org.openrdf.rio.*;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFParseException;
+import org.openrdf.rio.Rio;
 import org.slf4j.Logger;
 
 import javax.annotation.PostConstruct;
@@ -70,9 +66,6 @@ public class LdpWebService {
     private ConfigurationService configurationService;
 
     @Inject
-    private SesameService sesameService;
-
-    @Inject
     private LdpService ldpService;
 
     @PostConstruct
@@ -86,7 +79,7 @@ public class LdpWebService {
         if (log.isDebugEnabled()) {
             log.debug("GET to PDP-R <{}>", getResourceUri(uriInfo));
         }
-        return doGetHead(uriInfo, r ,type).build();
+        return buildResourceResponse(uriInfo, r, type).build();
     }
 
     @HEAD
@@ -95,18 +88,15 @@ public class LdpWebService {
         if (log.isDebugEnabled()) {
             log.debug("HEAD to PDP-R <{}>", getResourceUri(uriInfo));
         }
-        return doGetHead(uriInfo, r, type).entity(null).build();
+        return buildResourceResponse(uriInfo, r, type).entity(null).build();
     }
 
-    private Response.ResponseBuilder doGetHead(final UriInfo uriInfo, Request r, MediaType type)
-            throws RepositoryException {
+    private Response.ResponseBuilder buildResourceResponse(final UriInfo uriInfo, Request r, MediaType type) throws RepositoryException {
         final String subject = getResourceUri(uriInfo);
 
-        Response.ResponseBuilder rb404 = check404(subject);
-        if (rb404 != null) {
-            return createResponse(rb404, uriInfo);
+        if (!ldpService.exists(getResourceUri(uriInfo))) {
+            return Response.status(Response.Status.NOT_FOUND);
         }
-        // log.warn("NOT CHECKING EXISTENCE OF <{}>", subject);
 
         // TODO: Maybe this is a LDP-BR?
         // TODO: Proper content negotiation
@@ -121,30 +111,9 @@ public class LdpWebService {
                 @Override
                 public void write(OutputStream output) throws IOException, WebApplicationException {
                     try {
-                        RepositoryConnection con = sesameService.getConnection();
-                        try {
-                            con.begin();
-                            URI s = con.getValueFactory().createURI(subject),
-                                ldpContext = con.getValueFactory().createURI(LDP.NAMESPACE);
-                            // TODO: this should be a little more sophisticated...
-                            // TODO: non-membership triples flag / Prefer-header
-                            RDFWriter writer = Rio.createWriter(format, output);
-                            UnionIteration<Statement, RepositoryException> union = new UnionIteration<>(
-                                    con.getStatements(null, null, null, false, s),
-                                    con.getStatements(s, null, null, false, ldpContext)
-                            );
-                            try {
-                                LdpWebServiceUtils.exportIteration(writer, s, union);
-                            } finally {
-                                union.close();
-                            }
-                            con.commit();
-                        } catch (RDFHandlerException e) {
-                            con.rollback();
-                            throw new WebApplicationException(e, createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).build());
-                        } finally {
-                            con.close();
-                        }
+                        ldpService.exportResource(output, subject, format);
+                    } catch (RDFHandlerException e) {
+                        throw new WebApplicationException(e, createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).build());
                     } catch (RepositoryException e) {
                         throw new WebApplicationException(e, createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).build());
                     }
@@ -187,75 +156,11 @@ public class LdpWebService {
         }
 
         String newResource = uriInfo.getRequestUriBuilder().path(localName).build().toString();
-        final RepositoryConnection con = sesameService.getConnection();
         try {
-            final URI c = con.getValueFactory().createURI(container);
-            final URI ldpContext = con.getValueFactory().createURI(LDP.NAMESPACE);
-            con.begin();
-
-            URI s = con.getValueFactory().createURI(newResource);
-            log.trace("Checking possible name clash for new resource <{}>", newResource);
-            if (con.hasStatement(s, null, null, false, ldpContext)) {
-                int i = 0;
-                final String base = newResource;
-                do {
-                    final String candidate = base + "-" + (++i);
-                    log.trace("<{}> already exists, trying <{}>", s.stringValue(), candidate);
-                    s = con.getValueFactory().createURI(candidate);
-                } while (con.hasStatement(s, null, null, false, ldpContext));
-                newResource = s.stringValue();
-                log.debug("resolved name clash, new resource will be <{}>", newResource);
-            } else {
-                log.debug("no name clash for <{}>", newResource);
-            }
-
-            log.debug("POST to <{}> will create new LDP-R <{}>", container, newResource);
-
-            // Add container triples (Sec. 6.4.3)
-            // container and meta triples!
-
-            Literal now = con.getValueFactory().createLiteral(new Date());
-
-            con.add(c, RDF.TYPE, LDP.BasicContainer, ldpContext);
-            con.add(c, LDP.contains, s, ldpContext);
-            con.remove(c, DCTERMS.modified, null, ldpContext);
-            con.add(c, DCTERMS.modified, now, ldpContext);
-
-            con.add(s, RDF.TYPE, LDP.Resource, ldpContext);
-            con.add(s, DCTERMS.created, now, ldpContext);
-            con.add(s, DCTERMS.modified, now, ldpContext);
-
-            // LDP-BC for now!
-            con.commit();
-
-            // Add the bodyContent
-            log.trace("Content ({}) for new resource <{}>", type, newResource);
-            final RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(type.toString());
-            if (rdfFormat == null) {
-                log.debug("POST creates new LDP-BR with type {}", type);
-                log.warn("LDP-BR not (yet) supported!");
-                return createResponse(Response.Status.NOT_IMPLEMENTED, uriInfo).entity("LDP-BR not (yet) supported").build();
-            } else {
-                log.debug("POST creates new LDP-RR, data provided as {}", rdfFormat.getName());
-                try {
-                    con.begin();
-
-                    // FIXME: We are (are we?) allowed to filter out server-managed properties here
-                    con.add(postBody, newResource, rdfFormat, s);
-
-                    con.commit();
-                    return createResponse(Response.Status.CREATED, uriInfo).location(java.net.URI.create(newResource)).build();
-                } catch (IOException | RDFParseException e) {
-                    return createResponse(Response.Status.BAD_REQUEST, uriInfo).entity(e.getClass().getSimpleName() + ": "+ e.getMessage()).build();
-                }
-            }
-        } catch (final Throwable t) {
-            if (con.isActive()) {
-                con.rollback();
-            }
-            throw t;
-        } finally {
-            con.close();
+            ldpService.addResource(postBody, type, container, newResource);
+            return createResponse(Response.Status.CREATED, uriInfo).location(java.net.URI.create(newResource)).build();
+        } catch (IOException | RDFParseException e) {
+            return createResponse(Response.Status.BAD_REQUEST, uriInfo).entity(e.getClass().getSimpleName() + ": "+ e.getMessage()).build();
         }
     }
 
@@ -279,20 +184,11 @@ public class LdpWebService {
         } else {
             // check ETag -> 412 Precondition Failed (Sec. 5.5.3)
             log.trace("Checking If-Match: {}", eTag);
-            final RepositoryConnection con = sesameService.getConnection();
-            try {
-                con.begin();
-                EntityTag hasTag = generateETag(con, resource);
-                con.commit();
-
-                if (!EntityTagUtils.equals(eTag, hasTag)) {
-                    log.trace("If-Match header did not match, expected {}", hasTag);
-                    return createResponse(Response.Status.PRECONDITION_FAILED, uriInfo).build();
-                }
-            } finally {
-                con.close();
+            EntityTag hasTag = ldpService.generateETag(resource);
+            if (!EntityTagUtils.equals(eTag, hasTag)) {
+                log.trace("If-Match header did not match, expected {}", hasTag);
+                return createResponse(Response.Status.PRECONDITION_FAILED, uriInfo).build();
             }
-
         }
 
         /*
@@ -306,48 +202,21 @@ public class LdpWebService {
     }
 
     @DELETE
-    public Response DELETE(@Context UriInfo uriInfo) throws RepositoryException {
+    public Response DELETE(@Context UriInfo uriInfo) {
         /*
          * Handle delete (Sec. 5.6, Sec. 6.6)
          */
         final String resource = getResourceUri(uriInfo);
         log.debug("DELETE to <{}>", resource);
-
-        log.warn("NOT CHECKING EXISTENCE OF <{}>", resource);
-
-        final RepositoryConnection con = sesameService.getConnection();
         try {
-            con.begin();
-
-            URI s = con.getValueFactory().createURI(resource),
-                    ldpContext = con.getValueFactory().createURI(LDP.NAMESPACE);
-            Literal now = con.getValueFactory().createLiteral(new Date());
-
-            // Delete corresponding containment and membership triples (Sec. 6.6.1)
-            RepositoryResult<Statement> stmts = con.getStatements(null, LDP.member, s, false, ldpContext);
-            try {
-                while (stmts.hasNext()) {
-                    Statement st = stmts.next();
-                    con.remove(st.getSubject(), DCTERMS.modified, null);
-                    con.add(st.getSubject(), DCTERMS.modified, now);
-                    con.remove(st);
-                }
-            } finally {
-                stmts.close();
-            }
-            // Delete the resource meta
-            con.remove(s, null, null, ldpContext);
-
-            // Delete the resource data
-            con.clear(s);
-
-            con.commit();
+            ldpService.deleteResource(resource);
             return createResponse(Response.Status.NO_CONTENT, uriInfo).build();
-        } finally {
-            con.close();
+        } catch (RepositoryException e) {
+            log.error("Error deleting LDP-R: {}: {}", resource, e.getMessage());
+            return createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).entity("Error deleting LDP-R: " + e.getMessage()).build();
         }
-    }
 
+    }
 
     @PATCH
     public Response PATCH() {
@@ -383,27 +252,6 @@ public class LdpWebService {
         return builder.build();
     }
 
-    protected Response.ResponseBuilder check404(UriInfo uriInfo) throws RepositoryException {
-        return check404(getResourceUri(uriInfo));
-    }
-
-    protected Response.ResponseBuilder check404(String resourceUri) throws RepositoryException {
-        final RepositoryConnection con = sesameService.getConnection();
-        try {
-            con.begin();
-            final URI resource = con.getValueFactory().createURI(resourceUri),
-                ldpContext = con.getValueFactory().createURI(LDP.NAMESPACE);
-            if (con.hasStatement(resource, RDF.TYPE, null, true, ldpContext)) {
-                return null;
-            } else {
-                return Response.status(Response.Status.NOT_FOUND);
-            }
-        } finally {
-            con.commit();
-            con.close();
-        }
-    }
-
     protected Response.ResponseBuilder createResponse(int status, UriInfo uriInfo) {
         return createResponse(Response.status(status), uriInfo);
     }
@@ -421,31 +269,16 @@ public class LdpWebService {
 
         final String rUri = getResourceUri(uriInfo);
         try {
-            final RepositoryConnection con = sesameService.getConnection();
-            try {
-                con.begin();
-                final URI uri = con.getValueFactory().createURI(rUri),
-                        ldp = con.getValueFactory().createURI(LDP.NAMESPACE);
-
-                // Link rel='type' Headers (Sec. 5.2.8, 6.2.8)
-                RepositoryResult<Statement> types = con.getStatements(uri, RDF.TYPE, null, false, ldp);
-                try {
-                    while (types.hasNext()) {
-                        Value o = types.next().getObject();
-                        if (o instanceof URI && o.stringValue().startsWith(LDP.NAMESPACE)) {
-                            rb.link(o.stringValue(), "type");
-                        }
-                    }
-                } finally {
-                    types.close();
+            List<Statement> statements = ldpService.getStatements(rUri);
+            for (Statement stmt : statements) {
+                Value o = stmt.getObject();
+                if (o instanceof URI && o.stringValue().startsWith(LDP.NAMESPACE)) {
+                    rb.link(o.stringValue(), "type");
                 }
-
-                // ETag (Sec. 5.2.7)
-                rb.tag(generateETag(con, uri));
-                con.commit();
-            } finally {
-                con.close();
             }
+
+            // ETag (Sec. 5.2.7)
+            rb.tag(ldpService.generateETag(rUri));
         } catch (RepositoryException e) {
             log.error("Could not set ldp-response headers", e);
         }
@@ -474,36 +307,6 @@ public class LdpWebService {
         return uri;
     }
 
-
-    protected static EntityTag generateETag(RepositoryConnection con, String uri) throws RepositoryException {
-        return generateETag(con, con.getValueFactory().createURI(uri));
-    }
-
-    protected static EntityTag generateETag(RepositoryConnection con, URI uri) throws RepositoryException {
-        final URI ldpContext = con.getValueFactory().createURI(LDP.NAMESPACE);
-        final RepositoryResult<Statement> stmts = con.getStatements(uri, DCTERMS.modified, null, true, ldpContext);
-        try {
-            // TODO: ETag is the last-modified date (explicitly managed) thus only weak.
-            Date latest = null;
-            while (stmts.hasNext()) {
-                Value o = stmts.next().getObject();
-                if (o instanceof Literal) {
-                    Date d = ((Literal)o).calendarValue().toGregorianCalendar().getTime();
-                    if (latest == null || d.after(latest)) {
-                        latest = d;
-                    }
-                }
-            }
-            if (latest != null) {
-                return new EntityTag(String.valueOf(latest.getTime()), true);
-            } else {
-                return null;
-            }
-        } finally {
-            stmts.close();
-        }
-    }
-
     /**
      * FIXME: THIS SHOULD GO AWAY!
      */