/** * Check the constraints of a graph. * @param graph the graph * @param type the LDP interaction model * @param syntax the output syntax */ protected void checkConstraint(final Graph graph, final IRI type, final RDFSyntax syntax) { ofNullable(graph).map(g -> constraintServices.stream().parallel().flatMap(svc -> svc.constrainedBy(type, g)).collect(toList())) .filter(violations -> !violations.isEmpty()) .map(violations -> { final ResponseBuilder err = status(CONFLICT); violations.forEach(v -> err.link(v.getConstraint().getIRIString(), LDP.constrainedBy.getIRIString())); final StreamingOutput stream = new StreamingOutput() { @Override public void write(final OutputStream out) throws IOException { getServices().getIOService().write(violations.stream().flatMap(v2 -> v2.getTriples().stream()), out, syntax); } }; return err.entity(stream); }).ifPresent(err -> { throw new ClientErrorException(err.build()); }); }
private void addLdpHeaders(final ResponseBuilder builder, final IRI model) { ldpResourceTypes(model).forEach(type -> { builder.link(type.getIRIString(), "type"); // Mementos don't accept POST or PATCH if (LDP.Container.equals(type) && !isMemento) { builder.header(ACCEPT_POST, getServices().getIOService().supportedWriteSyntaxes().stream() .map(RDFSyntax::mediaType).collect(joining(","))); } else if (LDP.RDFSource.equals(type) && !isMemento) { builder.header(ACCEPT_PATCH, getServices().getIOService().supportedUpdateSyntaxes().stream() .map(RDFSyntax::mediaType).collect(joining(","))); } }); }
@Override public Response toResponse(final TombstoneException e) { debugException(this, e, LOGGER); final Response.ResponseBuilder response = status(GONE) .entity(e.getMessage()); if (e.getURI() != null) { response.link(e.getURI(), "hasTombstone"); } return response.type(TEXT_PLAIN_TYPE).build(); } }
violations.forEach(v -> err.link(v.getConstraint().getIRIString(), LDP.constrainedBy.getIRIString())); throw new ClientErrorException(err.build());
Value o = stmt.getObject(); if (o instanceof URI && o.stringValue().startsWith(LDP.NAMESPACE)) { rb.link(o.stringValue(), LINK_REL_TYPE); if (rdfSource != null) { rb.link(rdfSource.stringValue(), LINK_REL_DESCRIBEDBY); rb.link(rdfSource.stringValue(), LINK_REL_META); rb.link(nonRdfSource.stringValue(), LINK_REL_CONTENT);
} else if (!supportsInteractionModel(LDP.RDFSource)) { throw new BadRequestException(status(BAD_REQUEST) .link(UnsupportedInteractionModel.getIRIString(), LDP.constrainedBy.getIRIString()) .entity("Unsupported interaction model provided").type(TEXT_PLAIN_TYPE).build()); } else if (isNull(syntax)) {
final String description = base + (base.contains("?") ? "&" : "?") + "ext=description"; if (nonNull(syntax)) { builder.link(description, "canonical").link(base, "describes") .link(base + "#description", "alternate"); } else { builder.link(base, "canonical").link(description, "describedby") .type(ds.getMimeType().orElse(APPLICATION_OCTET_STREAM)); builder.link(getSelfIdentifier(), "self");
builder.link(getIdentifier() + "?ext=description", "describedby"); } else { readEntityIntoDataset(PreferUserManaged, ofNullable(rdfSyntax).orElse(TURTLE), mutable); .thenCompose(future -> emitEvent(internalId, AS.Create, ldpType)) .thenApply(future -> { ldpResourceTypes(ldpType).map(IRI::getIRIString).forEach(type -> builder.link(type, "type")); return builder.location(create(getIdentifier())); });
final List<Link> links = getMementoLinks(identifier, mementos).collect(toList()); final ResponseBuilder builder = ok().link(identifier, ORIGINAL + " " + TIMEGATE); builder.links(links.stream().map(this::filterLinkParams).toArray(Link[]::new)) .link(Resource.getIRIString(), TYPE).link(RDFSource.getIRIString(), TYPE) .header(ALLOW, join(",", GET, HEAD, OPTIONS));
.forEach(type -> builder.link(type.getIRIString(), "type"));
status(BAD_REQUEST).link(UnsupportedInteractionModel.getIRIString(), LDP.constrainedBy.getIRIString()).build());
/** * Initialize the response. * @param parent the parent resource * @param child the child resource * @return a response builder */ public ResponseBuilder initialize(final Resource parent, final Resource child) { if (MISSING_RESOURCE.equals(parent)) { // Can't POST to a missing resource throw new NotFoundException(); } else if (DELETED_RESOURCE.equals(parent)) { // Can't POST to a deleted resource throw new ClientErrorException(GONE); } else if (ACL.equals(getRequest().getExt()) || ldpResourceTypes(parent.getInteractionModel()).noneMatch(LDP.Container::equals)) { // Can't POST to an ACL resource or non-Container throw new NotAllowedException(GET, Stream.of(HEAD, OPTIONS, PATCH, PUT, DELETE).toArray(String[]::new)); } else if (!MISSING_RESOURCE.equals(child) && !DELETED_RESOURCE.equals(child)) { throw new ClientErrorException(CONFLICT); } else if (!supportsInteractionModel(ldpType)) { throw new BadRequestException("Unsupported interaction model provided", status(BAD_REQUEST) .link(UnsupportedInteractionModel.getIRIString(), LDP.constrainedBy.getIRIString()).build()); } else if (ldpType.equals(LDP.NonRDFSource) && nonNull(rdfSyntax)) { LOGGER.error("Cannot save {} as a NonRDFSource with RDF syntax", getIdentifier()); throw new BadRequestException("Cannot save resource as a NonRDFSource with RDF syntax"); } setParent(parent); return status(CREATED); }
/** * Get the standard headers. * @param builder the response builder * @return the response builder */ public ResponseBuilder standardHeaders(final ResponseBuilder builder) { // Standard HTTP Headers builder.lastModified(from(getResource().getModified())).header(VARY, ACCEPT); final IRI model; if (isNull(getRequest().getExt()) || DESCRIPTION.equals(getRequest().getExt())) { if (nonNull(syntax)) { builder.header(VARY, PREFER); builder.type(syntax.mediaType()); } model = getResource().getBinaryMetadata().isPresent() && nonNull(syntax) ? LDP.RDFSource : getResource().getInteractionModel(); // Link headers from User data getResource().getExtraLinkRelations().collect(toMap(Entry::getKey, Entry::getValue)) .entrySet().forEach(entry -> builder.link(entry.getKey(), join(" ", entry.getValue()))); } else { model = LDP.RDFSource; } // Add LDP-required headers addLdpHeaders(builder, model); // Memento-related headers addMementoHeaders(builder); return builder; }
/** * Initialze the handler with a Trellis resource. * * @param parent the parent resource * @param resource the Trellis resource * @return a response builder */ public ResponseBuilder initialize(final Resource parent, final Resource resource) { // Check that the persistence layer supports LDP-R if (MISSING_RESOURCE.equals(resource)) { // Can't delete a non-existent resources throw new NotFoundException(); } else if (DELETED_RESOURCE.equals(resource)) { // Can't delete a non-existent resources throw new ClientErrorException(GONE); } else if (!supportsInteractionModel(LDP.Resource)) { throw new ClientErrorException(status(BAD_REQUEST) .link(UnsupportedInteractionModel.getIRIString(), LDP.constrainedBy.getIRIString()) .entity("Unsupported interaction model provided").type(TEXT_PLAIN_TYPE).build()); } // Check the cache final EntityTag etag = new EntityTag(buildEtagHash(getIdentifier(), resource.getModified(), null)); checkCache(resource.getModified(), etag); setResource(resource); resource.getContainer().ifPresent(p -> setParent(parent)); return noContent(); }
/** * Update the resource in the persistence layer. * * @param builder the Trellis response builder * @return a response builder promise */ public CompletionStage<ResponseBuilder> updateResource(final ResponseBuilder builder) { LOGGER.debug("Updating {} via PATCH", getIdentifier()); // Add the LDP link types if (ACL.equals(getRequest().getExt())) { getLinkTypes(LDP.RDFSource).forEach(type -> builder.link(type, "type")); } else { getLinkTypes(getResource().getInteractionModel()).forEach(type -> builder.link(type, "type")); } final TrellisDataset mutable = TrellisDataset.createDataset(); final TrellisDataset immutable = TrellisDataset.createDataset(); return assembleResponse(mutable, immutable, builder) .whenComplete((a, b) -> mutable.close()) .whenComplete((a, b) -> immutable.close()); }
/** * Create a response builder for a TimeGate response. * * @param mementos the list of memento ranges * @param req the LDP request * @param baseUrl the base URL * @return a response builder object */ public ResponseBuilder getTimeGateBuilder(final SortedSet<Instant> mementos, final TrellisRequest req, final String baseUrl) { final String identifier = getBaseUrl(baseUrl, req) + req.getPath(); return status(FOUND) .location(fromUri(identifier + "?version=" + req.getDatetime().getInstant().getEpochSecond()).build()) .link(identifier, ORIGINAL + " " + TIMEGATE) .links(getMementoLinks(identifier, mementos).map(this::filterLinkParams).toArray(Link[]::new)) .header(VARY, ACCEPT_DATETIME); }
/** * Add the memento headers. * @param builder the ResponseBuilder * @param mementos the list of memento ranges * @return the response builder */ public ResponseBuilder addMementoHeaders(final ResponseBuilder builder, final SortedSet<Instant> mementos) { // Only show memento links for the user-managed graph (not ACL) if (!ACL.equals(getRequest().getExt())) { builder.link(getIdentifier(), "original timegate") .links(MementoResource.getMementoLinks(getIdentifier(), mementos) .map(link -> MementoResource.filterLinkParams(link, !includeMementoDates)) .toArray(Link[]::new)); } return builder; }
public Response.ResponseBuilder toResponse(HalItem item) { int statusCode = item.getHttpStatusCode().getCode(); Response.ResponseBuilder builder = Response .status(statusCode) .entity(item); if (statusCode == HttpStatusCode.CREATED.getCode()) { HalLink link = item.get_links().getLink("self"); builder.location(link.getHref()); } for (Map.Entry<String, HalLink> entry : item.get_links().entrySet()) { String rel = entry.getKey(); HalLink link = entry.getValue(); builder.link(link.getHref(), rel); } return builder; }
/** * Add the non-resource related headers specified in LDP to the provided ResponseBuilder * @param rb the ResponseBuilder to decorate * @return the updated ResponseBuilder for chaining */ protected Response.ResponseBuilder createResponse(Response.ResponseBuilder rb) { // Link rel='http://www.w3.org/ns/ldp#constrainedBy' (Sec. 4.2.1.6) rb.link(LDP_SERVER_CONSTRAINTS, LINK_REL_CONSTRAINEDBY); return rb; }