MARMOTTA-449: LDP-NR now working - only some minimal tweaks were missing
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/22d6735e Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/22d6735e Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/22d6735e Branch: refs/heads/develop Commit: 22d6735ea6f12bb071cdf1067a7370d624fda8e5 Parents: 679e99f Author: Jakob Frank <[email protected]> Authored: Mon Mar 10 15:44:07 2014 +0100 Committer: Jakob Frank <[email protected]> Committed: Mon Mar 10 15:44:07 2014 +0100 ---------------------------------------------------------------------- .../marmotta/platform/ldp/api/LdpService.java | 10 ++-- .../ldp/services/LdpBinaryStoreServiceImpl.java | 50 ++++++++++---------- .../platform/ldp/services/LdpServiceImpl.java | 43 ++++++++++++----- .../platform/ldp/webservices/LdpWebService.java | 32 +++++++++---- .../ldp/webservices/LdpWebServiceTest.java | 8 ++-- 5 files changed, 90 insertions(+), 53 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/22d6735e/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 8f49e82..01c4db4 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 @@ -48,7 +48,7 @@ public interface LdpService { boolean exists(RepositoryConnection connection, URI resource) throws RepositoryException; - boolean exists(RepositoryConnection connection, URI resource, URI type) throws RepositoryException; + boolean hasType(RepositoryConnection connection, URI resource, URI type) throws RepositoryException; /** * Add a LDP resource @@ -88,9 +88,9 @@ public interface LdpService { void exportResource(RepositoryConnection connection, URI resource, OutputStream output, RDFFormat format) throws RepositoryException, RDFHandlerException; - void exportResource(RepositoryConnection connection, String resource, OutputStream out) throws RepositoryException, IOException; + void exportBinaryResource(RepositoryConnection connection, String resource, OutputStream out) throws RepositoryException, IOException; - void exportResource(RepositoryConnection connection, URI resource, OutputStream out) throws RepositoryException, IOException; + void exportBinaryResource(RepositoryConnection connection, URI resource, OutputStream out) throws RepositoryException, IOException; EntityTag generateETag(RepositoryConnection connection, String uri) throws RepositoryException; @@ -107,4 +107,8 @@ public interface LdpService { Date getLastModified(RepositoryConnection connection, URI uri) throws RepositoryException; void patchResource(RepositoryConnection connection, String resource, InputStream patchData, boolean strict) throws RepositoryException, ParseException, InvalidModificationException, InvalidPatchDocumentException; + + String getMimeType(RepositoryConnection connection, String resource) throws RepositoryException; + + String getMimeType(RepositoryConnection connection, URI uri) throws RepositoryException; } http://git-wip-us.apache.org/repos/asf/marmotta/blob/22d6735e/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java index 20741b1..01a305f 100644 --- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java +++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java @@ -17,19 +17,26 @@ */ package org.apache.marmotta.platform.ldp.services; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.marmotta.platform.core.api.config.ConfigurationService; +import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent; import org.apache.marmotta.platform.core.events.SystemStartupEvent; import org.apache.marmotta.platform.ldp.api.LdpBinaryStoreService; import org.openrdf.model.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; import java.io.*; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; /** * Very basic disk-based implementation of the LDP Binary Store @@ -44,17 +51,16 @@ public class LdpBinaryStoreServiceImpl implements LdpBinaryStoreService { @Inject private ConfigurationService configurationService; - private File base; + private Path base; - public void init(@Observes SystemStartupEvent e) { - base = new File(configurationService.getHome(), "data"); - if (!base.exists()) { - base.mkdir(); - } - log.info("Initialized binary data store over {}", base.getAbsolutePath()); + @PostConstruct + public void init() { + base = Paths.get(configurationService.getHome(), "data"); + + log.info("Initialized binary data store over {}", base.toString()); } - private File getFile(String resource) throws URISyntaxException { + private Path getFile(String resource) throws URISyntaxException { java.net.URI uri = new java.net.URI(resource); String schema = uri.getScheme(); if ("http".compareTo(schema) != 0) { @@ -62,27 +68,18 @@ public class LdpBinaryStoreServiceImpl implements LdpBinaryStoreService { log.error(msg); throw new RuntimeException(msg); } - return new File(base, StringUtils.removeStart(resource, "http://")); + return base.resolve(StringUtils.removeStart(resource, "http://")); } @Override public boolean store(String resource, InputStream stream) { try { - File file = getFile(resource); - File dir = file.getParentFile(); - if (!dir.exists()) { - dir.mkdirs(); - } + Path file = getFile(resource); + Files.createDirectories(file.getParent()); - OutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); - int token = -1; - while((token = stream.read()) != -1) { - bufferedOutputStream.write(token); + try (OutputStream outputStream = Files.newOutputStream(file, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { + IOUtils.copy(stream, outputStream); } - bufferedOutputStream.flush(); - bufferedOutputStream.close(); - stream.close(); - return true; } catch (URISyntaxException | IOException e) { log.error("{} resource cannot be stored on disk: {}", resource, e.getMessage()); @@ -98,11 +95,12 @@ public class LdpBinaryStoreServiceImpl implements LdpBinaryStoreService { @Override public InputStream read(String resource) throws IOException { try { - File file = getFile(resource); - if (!file.exists()) { - throw new IOException("File " + file.getAbsolutePath() + " not found"); + Path file = getFile(resource); + if (Files.exists(file)) { + return Files.newInputStream(file, StandardOpenOption.READ); } else { - return new FileInputStream(file); + log.warn("{} not found in binary storage ({})", resource, file); + return null; } } catch (URISyntaxException e) { log.error("Error reading resource {}: {}", resource, e.getMessage()); http://git-wip-us.apache.org/repos/asf/marmotta/blob/22d6735e/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 f7724f2..f1af941 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 @@ -91,7 +91,7 @@ public class LdpServiceImpl implements LdpService { } @Override - public boolean exists(RepositoryConnection connection, URI resource, URI type) throws RepositoryException { + public boolean hasType(RepositoryConnection connection, URI resource, URI type) throws RepositoryException { return connection.hasStatement(resource, RDF.TYPE, type, true, ldpContext); } @@ -133,20 +133,37 @@ public class LdpServiceImpl implements LdpService { } @Override - public void exportResource(RepositoryConnection connection, String resource, OutputStream out) throws RepositoryException, IOException { + public void exportBinaryResource(RepositoryConnection connection, String resource, OutputStream out) throws RepositoryException, IOException { //TODO: check (resource, dct:format, type) - InputStream in = binaryStore.read(resource); - if (in != null) { - IOUtils.copy(in, out); - } else { - throw new IOException("Cannot read resource " + resource); + try (InputStream in = binaryStore.read(resource)) { + if (in != null) { + IOUtils.copy(in, out); + } else { + throw new IOException("Cannot read resource " + resource); + } } } @Override - public void exportResource(RepositoryConnection connection, URI resource, OutputStream out) throws RepositoryException, IOException { - exportResource(connection, resource.stringValue(), out); + public void exportBinaryResource(RepositoryConnection connection, URI resource, OutputStream out) throws RepositoryException, IOException { + exportBinaryResource(connection, resource.stringValue(), out); + } + + @Override + public String getMimeType(RepositoryConnection connection, String resource) throws RepositoryException { + return getMimeType(connection, buildURI(resource)); + } + + @Override + public String getMimeType(RepositoryConnection connection, URI uri) throws RepositoryException { + final RepositoryResult<Statement> formats = connection.getStatements(uri, DCTERMS.format, null, false, ldpContext); + try { + if (formats.hasNext()) return formats.next().getObject().stringValue(); + } finally { + formats.close(); + } + return null; } @Override @@ -161,9 +178,9 @@ public class LdpServiceImpl implements LdpService { // Add container triples (Sec. 6.4.3) // container and meta triples! - Literal now = valueFactory.createLiteral(new Date()); + final Literal now = valueFactory.createLiteral(new Date()); - if (exists(connection, container, LDP.BasicContainer)) { + if (hasType(connection, container, LDP.BasicContainer)) { connection.remove(container, DCTERMS.modified, null, ldpContext); } else { connection.add(container, RDF.TYPE, LDP.BasicContainer, ldpContext); @@ -173,7 +190,7 @@ public class LdpServiceImpl implements LdpService { connection.add(container, DCTERMS.modified, now, ldpContext); connection.add(resource, RDF.TYPE, LDP.Resource, ldpContext); - connection.add(resource, RDF.TYPE, LDP.NonRdfResource, ldpContext); + connection.add(resource, RDF.TYPE, LDP.RdfResource, ldpContext); connection.add(resource, DCTERMS.created, now, ldpContext); connection.add(resource, DCTERMS.modified, now, ldpContext); @@ -186,6 +203,8 @@ public class LdpServiceImpl implements LdpService { connection.add(binaryResource, DCTERMS.created, now, ldpContext); connection.add(binaryResource, DCTERMS.modified, now, ldpContext); + connection.add(binaryResource, RDF.TYPE, LDP.Resource, ldpContext); + connection.add(binaryResource, RDF.TYPE, LDP.NonRdfResource, ldpContext); //extra triples //TODO: check conformance with 6.2.3.12 http://git-wip-us.apache.org/repos/asf/marmotta/blob/22d6735e/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 75515a1..38ff9b0 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 @@ -99,38 +99,54 @@ public class LdpWebService { try { conn.begin(); + log.trace("Checking existence of {}", resource); if (!ldpService.exists(conn, resource)) { + log.debug("{} does not exist", resource); final Response.ResponseBuilder resp = createResponse(conn, Response.Status.NOT_FOUND, resource); conn.rollback(); return resp; + } else { + log.trace("{} hasType, continuing", resource); } // TODO: Maybe this is a LDP-BR? // TODO: Proper content negotiation - final RDFFormat format = Rio.getWriterFormatForMIMEType(type.toString(), RDFFormat.TURTLE); + final RDFFormat format = Rio.getWriterFormatForMIMEType(type.toString()); if (format == null) { log.warn("GET to <{}> with non-RDF format {}, so looking for a LDP-BR", resource, type); final StreamingOutput entity = new StreamingOutput() { @Override public void write(OutputStream out) throws IOException, WebApplicationException { try { - ldpService.exportResource(conn, resource, out); - } catch (RepositoryException | IOException e) { + final RepositoryConnection outputConn = sesameService.getConnection(); + try { + outputConn.begin(); + ldpService.exportBinaryResource(outputConn, resource, out); + outputConn.commit(); + } catch (RepositoryException | IOException e) { + outputConn.rollback(); + throw new WebApplicationException(e, createResponse(Response.status(Response.Status.INTERNAL_SERVER_ERROR)).entity(e).build()); + } finally { + outputConn.close(); + } + } catch (RepositoryException e) { throw new WebApplicationException(e, createResponse(Response.status(Response.Status.INTERNAL_SERVER_ERROR)).entity(e).build()); } } }; - final Response.ResponseBuilder resp = createResponse(conn, Response.Status.OK, resource).entity(entity).type(format.getDefaultMIMEType()); + final String realType = ldpService.getMimeType(conn, resource); + final Response.ResponseBuilder resp = createResponse(conn, Response.Status.OK, resource).entity(entity).type(realType!=null?MediaType.valueOf(realType):type); conn.commit(); return resp; } else { // Deliver all triples with <subject> as subject. + log.info("GET to <{}> with RDF format {}, providing LPD-RR data", resource, format.getDefaultMIMEType()); final StreamingOutput entity = new StreamingOutput() { @Override public void write(OutputStream output) throws IOException, WebApplicationException { try { - final RepositoryConnection outputConn = sesameService.getConnection();; + final RepositoryConnection outputConn = sesameService.getConnection(); try { outputConn.begin(); ldpService.exportResource(outputConn, resource, output, format); @@ -200,7 +216,7 @@ public class LdpWebService { final String base = newResource; do { final String candidate = base + "-" + (++i); - log.trace("<{}> already exists, trying <{}>", newResource, candidate); + log.trace("<{}> already hasType, trying <{}>", newResource, candidate); newResource = candidate; } while (ldpService.exists(conn, newResource)); log.debug("resolved name clash, new resource will be <{}>", newResource); @@ -210,7 +226,7 @@ public class LdpWebService { log.debug("POST to <{}> will create new LDP-R <{}>", container, newResource); - //checking if resource (container) exists is done later in the service + //checking if resource (container) hasType is done later in the service try { String location = ldpService.addResource(conn, container, newResource, type, postBody); final Response.ResponseBuilder response = createResponse(conn, Response.Status.CREATED, container).location(java.net.URI.create(location)); @@ -280,7 +296,7 @@ public class LdpWebService { * * clients should not be allowed to update LDPC-membership triples -> 409 Conflict (Sec. 6.5.1) * - * if the target resource exists, replace ALL data of the target. + * if the target resource hasType, replace ALL data of the target. */ final Response.ResponseBuilder resp = createResponse(con, Response.Status.NOT_IMPLEMENTED, resource); con.rollback(); http://git-wip-us.apache.org/repos/asf/marmotta/blob/22d6735e/platform/marmotta-ldp/src/test/java/org/apache/marmotta/platform/ldp/webservices/LdpWebServiceTest.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-ldp/src/test/java/org/apache/marmotta/platform/ldp/webservices/LdpWebServiceTest.java b/platform/marmotta-ldp/src/test/java/org/apache/marmotta/platform/ldp/webservices/LdpWebServiceTest.java index f1e6751..73497e0 100644 --- a/platform/marmotta-ldp/src/test/java/org/apache/marmotta/platform/ldp/webservices/LdpWebServiceTest.java +++ b/platform/marmotta-ldp/src/test/java/org/apache/marmotta/platform/ldp/webservices/LdpWebServiceTest.java @@ -98,7 +98,7 @@ public class LdpWebServiceTest { .header("Location", baseUrl + newResource) .post(container); - // now the container exists + // now the container hasType log.info("200 - container"); RestAssured .given() @@ -117,7 +117,7 @@ public class LdpWebServiceTest { )) .get(container); - // also the new resource exists + // also the new resource hasType RestAssured .given() .header("Accept", mimeType) @@ -183,7 +183,7 @@ public class LdpWebServiceTest { ) .post(container); - // now the container exists + // now the container hasType RestAssured .given() .header("Accept", RDFFormat.TURTLE.getDefaultMIMEType()) @@ -203,7 +203,7 @@ public class LdpWebServiceTest { .get(container); - // now the resource exists + // now the resource hasType RestAssured .given() .header("Accept", RDFFormat.TURTLE.getDefaultMIMEType())
