Stabilize Content-Negotiation for (Non)RdfSource Resources (to be continued)
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/e461f451 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/e461f451 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/e461f451 Branch: refs/heads/MARMOTTA-525 Commit: e461f451deb9a007faf451be89f6e7dec9439e17 Parents: c225e34 Author: Jakob Frank <[email protected]> Authored: Tue Sep 2 16:38:39 2014 +0200 Committer: Jakob Frank <[email protected]> Committed: Tue Sep 2 16:38:39 2014 +0200 ---------------------------------------------------------------------- .../platform/ldp/webservices/LdpWebService.java | 140 +++++++++++-------- 1 file changed, 83 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/e461f451/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 bdeb54f..d01f9bb 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 @@ -97,7 +97,7 @@ public class LdpWebService { return buildGetResponse(resource, r, type).entity(null).build(); } - private Response.ResponseBuilder buildGetResponse(final String resource, Request r, MediaType type) throws RepositoryException { + private Response.ResponseBuilder buildGetResponse(final String resource, Request r, MediaType acceptedType) throws RepositoryException { final RepositoryConnection conn = sesameService.getConnection(); try { conn.begin(); @@ -114,72 +114,91 @@ public class LdpWebService { // TODO: Proper content negotiation - final RDFFormat format; - if (type.isWildcardType()) { // No explicit Accept Header - if (ldpService.isRdfSourceResource(conn, resource)) { - format = RDFFormat.TURTLE; - } else { - format = null; - } - } else { - format = Rio.getWriterFormatForMIMEType(LdpUtils.getMimeType(type), null); - } - - if (format == null) { - log.debug("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 { - final RepositoryConnection outputConn = sesameService.getConnection(); + if (ldpService.isNonRdfSourceResource(conn, resource)) { // i.e. binary + log.debug("GET to <{}> which is a LDP-BR", resource, acceptedType); + final String rmt = ldpService.getMimeType(conn, resource); + final MediaType realType = rmt==null?null:MediaType.valueOf(rmt); + if (acceptedType == null || acceptedType.isCompatible(realType) || acceptedType.isWildcardType()) { + // Accept-Header compatible with the real type + final StreamingOutput entity = new StreamingOutput() { + @Override + public void write(OutputStream out) throws IOException, WebApplicationException { try { - outputConn.begin(); - ldpService.exportBinaryResource(outputConn, resource, out); - outputConn.commit(); - } catch (RepositoryException | IOException e) { - outputConn.rollback(); + 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()); - } 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(realType); + conn.commit(); + return resp; + } else { + log.debug("MediaType not acceptable for <{}>: '{}' (accept) vs. '{}' (found)", resource, acceptedType, realType); + // HTTP 406 + final Response.ResponseBuilder rsp = createResponse(conn, Response.Status.NOT_ACCEPTABLE, resource); + conn.commit(); + if (realType != null) { + rsp.entity(String.format("The requested resource <%s> is only available as '%s/%s'%n", resource, realType.getType(), realType.getSubtype())); + } else { + rsp.entity(String.format("The requested resource <%s> is only available as '*/*'%n", resource)); } - }; - 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; + return rsp; + } } else { // Deliver all triples from the <subject> context. - log.debug("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 RDFFormat format; + if (acceptedType == null || acceptedType.isWildcardType()) { // No explicit Accept Header + format = RDFFormat.TURTLE; + } else { + format = Rio.getWriterFormatForMIMEType(LdpUtils.getMimeType(acceptedType), null); + } + log.debug("GET to <{}> which is a LPD-RS, looking for {}", resource, format.getDefaultMIMEType()); + if (format == null) { + log.debug("Can't serialize LDP-RS to {}, no writer available"); + // HTTP 406 + final Response.ResponseBuilder rsp = createResponse(conn, Response.Status.NOT_ACCEPTABLE, resource); + conn.commit(); + rsp.entity(String.format("The requested resource <%s> is only available as '%s'%n", resource, RDFFormat.values())); + return rsp; + } else { + final StreamingOutput entity = new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { try { - outputConn.begin(); - ldpService.exportResource(outputConn, resource, output, format); - outputConn.commit(); - } catch (RDFHandlerException e) { - outputConn.rollback(); - throw new NoLogWebApplicationException(e, createResponse(Response.status(Response.Status.INTERNAL_SERVER_ERROR)).entity(e.getMessage()).build()); - } catch (final Throwable t) { - outputConn.rollback(); - throw t; - } finally { - outputConn.close(); + final RepositoryConnection outputConn = sesameService.getConnection(); + try { + outputConn.begin(); + ldpService.exportResource(outputConn, resource, output, format); + outputConn.commit(); + } catch (RDFHandlerException e) { + outputConn.rollback(); + throw new NoLogWebApplicationException(e, createResponse(Response.status(Response.Status.INTERNAL_SERVER_ERROR)).entity(e.getMessage()).build()); + } catch (final Throwable t) { + outputConn.rollback(); + throw t; + } finally { + outputConn.close(); + } + } catch (RepositoryException e) { + throw new WebApplicationException(e, createResponse(Response.status(Response.Status.INTERNAL_SERVER_ERROR)).entity(e).build()); } - } 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()); - conn.commit(); - return resp; + }; + final Response.ResponseBuilder resp = createResponse(conn, Response.Status.OK, resource).entity(entity).type(format.getDefaultMIMEType()); + conn.commit(); + return resp; + } } } catch (final Throwable t) { conn.rollback(); @@ -208,6 +227,13 @@ public class LdpWebService { try { conn.begin(); + // Check that all requred Headers are present + if (type == null) { + final Response.ResponseBuilder response = createResponse(conn, Response.Status.BAD_REQUEST, container); + conn.commit(); + return response.entity("Content-Type header is mandatory\n").build(); + } + // Check that the target container supports the LDPC Interaction Model final LdpService.InteractionModel containerModel = ldpService.getInteractionModel(conn, container); if (containerModel != LdpService.InteractionModel.LDPC) {
