You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ja...@apache.org on 2014/02/24 10:12:46 UTC
[4/5] git commit: MARMOTTA-440: extended LDP Stubs,
most are now functional (basic)
MARMOTTA-440: extended LDP Stubs, most are now functional (basic)
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/18005e1f
Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/18005e1f
Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/18005e1f
Branch: refs/heads/ldp
Commit: 18005e1f3b38d1a884bb6843ba8fccb3ff9e11c7
Parents: 1d9a5f6
Author: Jakob Frank <ja...@apache.org>
Authored: Wed Feb 19 12:28:35 2014 +0100
Committer: Jakob Frank <ja...@apache.org>
Committed: Wed Feb 19 12:28:35 2014 +0100
----------------------------------------------------------------------
.../platform/ldp/util/EntityTagUtils.java | 53 ++
.../platform/ldp/util/LdpWebServiceUtils.java | 19 +
.../platform/ldp/webservices/LdpWebService.java | 523 +++++++++++++++++--
3 files changed, 550 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/marmotta/blob/18005e1f/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/EntityTagUtils.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/EntityTagUtils.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/EntityTagUtils.java
new file mode 100644
index 0000000..bc58a60
--- /dev/null
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/EntityTagUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.marmotta.platform.ldp.util;
+
+import javax.ws.rs.core.EntityTag;
+
+/**
+ *
+ * @deprecated this is a workaround for <a href="https://issues.jboss.org/browse/RESTEASY-1019">RESTEASY-1019</a>
+ */
+@Deprecated
+public class EntityTagUtils {
+
+ /**
+ * This is a workaround for <a href="https://issues.jboss.org/browse/RESTEASY-1019">RESTEASY-1019</a>
+ *
+ * @see javax.ws.rs.core.EntityTag#equals(Object)
+ * @deprecated use {@link javax.ws.rs.core.EntityTag#equals(Object)} or {@link javax.ws.rs.core.Request#evaluatePreconditions(javax.ws.rs.core.EntityTag)} when RESTEASY-1019 is fixed.
+ */
+ @Deprecated
+ public static boolean equals(EntityTag tag1, EntityTag tag2) {
+ if (tag1 == null || tag2 == null) return false;
+
+ // If it works, it's fine
+ if (tag1.equals(tag2)) {
+ return true;
+ } else {
+ // Weak-Tag comparison requires extra check because of RESTEASY-1019
+ if (tag1.isWeak() && tag2.isWeak()) {
+ return tag1.getValue().replaceAll("^\"", "").equals(
+ tag2.getValue().replaceAll("^\"", "")
+ );
+ }
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/18005e1f/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
new file mode 100644
index 0000000..4033666
--- /dev/null
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
@@ -0,0 +1,19 @@
+package org.apache.marmotta.platform.ldp.util;
+
+/**
+ * Created by jakob on 2/18/14.
+ */
+public class LdpWebServiceUtils {
+
+ /**
+ * Urify the Slug: header value, i.e. replace all non-url chars with a single dash.
+ *
+ * @param slugHeaderValue
+ * @return the slugHeaderValue "urified"
+ */
+ public static String urify(String slugHeaderValue) {
+ return slugHeaderValue
+ // Replace non-url chars with '-'
+ .replaceAll("[^\\w]+", "-");
+ }
+}
http://git-wip-us.apache.org/repos/asf/marmotta/blob/18005e1f/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 bc1d584..8673ce2 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,23 +17,34 @@
*/
package org.apache.marmotta.platform.ldp.webservices;
-import javax.annotation.PostConstruct;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-import javax.ws.rs.*;
-import javax.ws.rs.core.*;
-
+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.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.slf4j.Logger;
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
-import java.util.UUID;
+import java.lang.annotation.Annotation;
+import java.util.*;
/**
* Linked Data Platform web services
@@ -50,8 +61,7 @@ public class LdpWebService {
public static final String PATH = "ldp";
- @Inject
- private Logger log;
+ private Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass());
@Inject
private ConfigurationService configurationService;
@@ -65,66 +75,234 @@ public class LdpWebService {
}
@GET
- public Response GET(@Context UriInfo uriInfo, @Context Request request, @PathParam("local") String localPart) {
- /* Both methods result in the absolute path, but which one is preferable? */
- log.trace("RequestUri: {}", uriInfo.getRequestUri());
- log.trace("BaseUri+LocalPart: {}ldp{}", uriInfo.getBaseUri(), localPart);
+ public Response GET(@Context final UriInfo uriInfo, @Context Request r, @HeaderParam(HttpHeaders.ACCEPT) MediaType type)
+ throws RepositoryException {
+ return doGetHead(uriInfo, r ,type).build();
+ }
+ private Response.ResponseBuilder doGetHead(final UriInfo uriInfo, Request r, MediaType type)
+ throws RepositoryException {
+ final String subject = getResourceUri(uriInfo);
+ log.debug("GET to PDP-R <{}>", subject);
+ log.warn("NOT CHECKING EXISTENCE OF <{}>", subject);
+
+ // TODO: Maybe this is a LDP-BR?
// TODO: Proper content negotiation
- final RDFFormat format = RDFFormat.TURTLE;
- final String subject = uriInfo.getRequestUri().toString();
+ r.evaluatePreconditions();
- // Deliver all triples with <subject> as subject.
+ final RDFFormat format = Rio.getWriterFormatForMIMEType(type.toString());
+ if (format == null) {
+ log.warn("GET to <{}> with unknown accept {}", subject, type);
+ return createResponse(Response.Status.NOT_IMPLEMENTED, uriInfo);
+ } else {
+ // Deliver all triples with <subject> as subject.
+ final StreamingOutput entity = new StreamingOutput() {
+ @Override
+ public void write(OutputStream output) throws IOException, WebApplicationException {
+ try {
+ RepositoryConnection con = sesameService.getConnection();
+ try {
+ con.begin();
+ URI s = con.getValueFactory().createURI(subject);
+ // TODO: this should be a little more sophisticated...
+ // TODO: non-membership triples flag
+ RDFWriter writer = Rio.createWriter(format, output);
+ con.exportStatements(s, null, null, false, writer);
- // use #createResponse to add global Headers.
- return createResponse(Response.Status.NOT_IMPLEMENTED, uriInfo).build();
+ con.commit();
+ } catch (RDFHandlerException e) {
+ con.rollback();
+ throw new WebApplicationException(e, createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).build());
+ } finally {
+ con.close();
+ }
+ } catch (RepositoryException e) {
+ throw new WebApplicationException(e, createResponse(Response.Status.INTERNAL_SERVER_ERROR, uriInfo).build());
+ }
+ }
+ };
+ return createResponse(Response.Status.OK, uriInfo).entity(entity).type(type);
+ }
}
+ /**
+ * LDP Post Request
+ *
+ * @see <a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp.html#ldpr-HTTP_POST">5.4 LDP-R POST</a>
+ * @see <a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp.html#ldpc-HTTP_POST">6.4 LDP-C POST</a>
+ */
@POST
- public Response POST(@Context UriInfo uriInfo, @Context Request request) {
+ public Response POST(@Context UriInfo uriInfo, @HeaderParam("Slug") String slug, InputStream postBody, @HeaderParam(HttpHeaders.CONTENT_TYPE) MediaType type)
+ throws RepositoryException {
/*
* TODO: POST implementation
* a POST to an existing resource converts this resource into an LDP-C
*/
- // Honor client wishes from Slug-header (Sec. 6.4.11)
- // http://www.ietf.org/rfc/rfc5023.txt
- final String localName = UUID.randomUUID().toString();
- final String container = uriInfo.getRequestUri().toString();
+ final String container = getResourceUri(uriInfo);
+ log.debug("POST to LDP-R <{}>", container);
+
+ // TODO: Check if resource exists
+ log.warn("NOT CHECKING EXISTENCE OF <{}>", container);
+
+ final String localName;
+ if (StringUtils.isBlank(slug)) {
+ /* Sec. 6.4.9) */
+ localName = UUID.randomUUID().toString();
+ } else {
+ // Honor client wishes from Slug-header (Sec. 6.4.11)
+ // http://www.ietf.org/rfc/rfc5023.txt
+ log.trace("Slug-Header is '{}'", slug);
+ localName = LdpWebServiceUtils.urify(slug);
+ log.trace("Slug-Header urified: {}", localName);
+ }
final String newResource = uriInfo.getRequestUriBuilder().path(localName).build().toString();
+ log.debug("POST to <{}> will create new LDP-R <{}>", container, newResource);
- // Add container triples (Sec. 6.4.3)
+ RepositoryConnection con = sesameService.getConnection();
+ try {
+ // Add container triples (Sec. 6.4.3)
+ con.begin();
+ // container and meta triples!
+ final URI c = con.getValueFactory().createURI(container);
+ final URI s = con.getValueFactory().createURI(newResource);
- // use #createResponse to add global Headers.
- // return createResponse(Response.Status.CREATED, uriInfo).location(java.net.URI.create(newResource)).build();
+ Literal now = con.getValueFactory().createLiteral(new Date());
- return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+ con.add(c, RDF.TYPE, LDP.BasicContainer);
+ con.add(c, LDP.member, s);
+ con.remove(c, DCTERMS.modified, null);
+ con.add(c, DCTERMS.modified, now);
+
+ con.add(s, DCTERMS.created, now);
+ con.add(s, DCTERMS.modified, now);
+ // 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);
+
+ 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();
+ }
}
@PUT
- public Response PUT(@Context UriInfo uriInfo, @Context Request request) {
+ public Response PUT(@Context UriInfo uriInfo, @Context Request request,
+ @HeaderParam(HttpHeaders.IF_MATCH) EntityTag eTag,
+ InputStream postBody, @HeaderParam(HttpHeaders.CONTENT_TYPE) MediaType type)
+ throws RepositoryException {
+ /*
+ * Handle PUT (Sec. 5.5, Sec. 6.5)
+ */
+ final String resource = getResourceUri(uriInfo);
+ log.debug("PUT to <{}>", resource);
+
+ log.warn("NOT CHECKING EXISTENCE OF <{}>", resource);
+
+ if (eTag == null) {
+ // check for If-Match header (ETag) -> 428 Precondition Required (Sec. 5.5.3)
+ log.trace("No If-Match header, but that's a MUST");
+ return createResponse(428, uriInfo).build();
+ } 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();
+ }
+
+ }
+
/*
* TODO: PUT implementation
*
- * check for If-Match header (ETag) -> 428 Precondition Required (Sec. 5.5.3)
- * check ETag -> 412 Precondition Failed (Sec. 5.5.3)
- * request.evaluatePreconditions(eTag)
- *
* 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.
*/
- return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+ return createResponse(Response.Status.NOT_IMPLEMENTED, uriInfo).build();
}
@DELETE
- public Response DELETE() {
+ public Response DELETE(@Context UriInfo uriInfo) throws RepositoryException {
+ /*
+ * 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);
+ 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);
+ 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
+ con.remove(s, null, null);
+
+
+ con.commit();
+ } finally {
+ con.close();
+ }
+
return Response.status(Response.Status.NOT_IMPLEMENTED).build();
}
@HEAD
- public Response HEAD() {
- return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+ public Response HEAD(@Context final UriInfo uriInfo, @Context Request r, @HeaderParam(HttpHeaders.ACCEPT) MediaType type)
+ throws RepositoryException {
+ final Response.ResponseBuilder rb = doGetHead(uriInfo, r, type);
+ rb.entity(null);
+ return rb.build();
}
@PATCH
@@ -133,24 +311,279 @@ public class LdpWebService {
}
@OPTIONS
- public Response OPTIONS() {
- return Response.status(Response.Status.NOT_IMPLEMENTED).build();
+ public Response OPTIONS(@Context final UriInfo uriInfo) {
+ /*
+ * Handle OPTIONS (Sec. 5.9, Sec. 6.9)
+ */
+ final String resource = getResourceUri(uriInfo);
+ log.debug("OPTIONS to <{}>", resource);
+
+ log.warn("NOT CHECKING EXISTENCE OF <{}>", resource);
+
+ Response.ResponseBuilder builder = createResponse(Response.Status.OK, uriInfo);
+
+ // Sec. 5.9.2
+ builder.allow("GET", "HEAD", "POST", "OPTIONS");
+
+ // Sec. 6.4.14 / Sec. 8.1
+ builder.header("Accept-Post", "text/turtle, */*");
+
+ // TODO: Sec. 5.8.2
+ //builder.header("Accept-Patch", null);
+
+
+ // TODO: Sec. 6.9.1
+ //builder.link(resource, "meta");
+
+
+ return builder.build();
}
protected Response.ResponseBuilder createResponse(int status, UriInfo uriInfo) {
final String targetURI = uriInfo.getRequestUri().toString();
- final Response.ResponseBuilder rb = Response.status(status);
+ return createResponse(Response.status(status), uriInfo);
+ }
- /* TODO: Add "global" Headers for LDP
- * - ETag (Sec. 5.2.7)
- * - Link rel='type' (Sec. 5.2.8 and 6.2.8)
- * - Link rel='describedby' (Sec. 5.2.11)
- */
+ protected Response.ResponseBuilder createResponse(Response.ResponseBuilder rb, UriInfo uriInfo) {
+ // Link LDP-R rel='type' (Sec. 5.2.8)
+ rb.link(LDP.Resource.stringValue(), "type");
+ // Link LDP-C rel='type' (Sec. 6.2.8)
+ rb.link(LDP.Container.stringValue(), "type");
+ rb.link(LDP.BasicContainer.stringValue(), "type");
+ // TODO: be more specific here? BasicContainer, DirectContainer, IndirectContainer
+
+ // Link rel='describedby' (Sec. 5.2.11)
+ rb.link("http://wiki.apache.org/marmotta/LDPImplementationReport", "describedby");
+
+ // ETag (Sec. 5.2.7)
+ final String rUri = getResourceUri(uriInfo);
+ try {
+ final RepositoryConnection con = sesameService.getConnection();
+ try {
+ con.begin();
+ rb.tag(generateETag(con, rUri));
+ con.commit();
+ } finally {
+ con.close();
+ }
+ } catch (RepositoryException e) {
+ log.error("Could not build ETag", e);
+ }
- return rb;
+ return new RB(rb);
}
protected Response.ResponseBuilder createResponse(Response.Status status, UriInfo uriInfo) {
return createResponse(status.getStatusCode(), uriInfo);
}
+
+ protected String getResourceUri(UriInfo uriInfo) {
+ final UriBuilder uriBuilder;
+ if (configurationService.getBooleanConfiguration("ldp.force_baseuri", false)) {
+ log.trace("UriBuilder is forced to configured baseuri <{}>", configurationService.getBaseUri());
+ uriBuilder = UriBuilder.fromUri(java.net.URI.create(configurationService.getBaseUri()));
+ } else {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ }
+ uriBuilder.path(PATH);
+ uriBuilder.path(uriInfo.getPathParameters().getFirst("local"));
+
+ String uri = uriBuilder.build().toString();
+ log.debug("RequestUri: {}", uri);
+ 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 {
+ RepositoryResult<Statement> stmts = con.getStatements(uri, DCTERMS.modified, null, true);
+ 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!
+ */
+ private class RB extends Response.ResponseBuilder {
+
+ private final Response.ResponseBuilder delegate;
+
+ @Override
+ public Response build() {
+ Response response = delegate.build();
+ log.trace("Sending Response {} ({})", response.getStatus(), response.getStatusInfo().getReasonPhrase());
+ return response;
+ }
+
+ @Override
+ public Response.ResponseBuilder clone() {
+ return delegate.clone();
+ }
+
+ @Override
+ public Response.ResponseBuilder status(int status) {
+ return delegate.status(status);
+ }
+
+ @Override
+ public Response.ResponseBuilder status(Response.StatusType status) {
+ return delegate.status(status);
+ }
+
+ @Override
+ public Response.ResponseBuilder status(Response.Status status) {
+ return delegate.status(status);
+ }
+
+ @Override
+ public Response.ResponseBuilder entity(Object entity) {
+ return delegate.entity(entity);
+ }
+
+ @Override
+ public Response.ResponseBuilder entity(Object entity, Annotation[] annotations) {
+ return delegate.entity(entity, annotations);
+ }
+
+ @Override
+ public Response.ResponseBuilder allow(String... methods) {
+ return delegate.allow(methods);
+ }
+
+ @Override
+ public Response.ResponseBuilder allow(Set<String> methods) {
+ return delegate.allow(methods);
+ }
+
+ @Override
+ public Response.ResponseBuilder cacheControl(CacheControl cacheControl) {
+ return delegate.cacheControl(cacheControl);
+ }
+
+ @Override
+ public Response.ResponseBuilder encoding(String encoding) {
+ return delegate.encoding(encoding);
+ }
+
+ @Override
+ public Response.ResponseBuilder header(String name, Object value) {
+ return delegate.header(name, value);
+ }
+
+ @Override
+ public Response.ResponseBuilder replaceAll(MultivaluedMap<String, Object> headers) {
+ return delegate.replaceAll(headers);
+ }
+
+ @Override
+ public Response.ResponseBuilder language(String language) {
+ return delegate.language(language);
+ }
+
+ @Override
+ public Response.ResponseBuilder language(Locale language) {
+ return delegate.language(language);
+ }
+
+ @Override
+ public Response.ResponseBuilder type(MediaType type) {
+ return delegate.type(type);
+ }
+
+ @Override
+ public Response.ResponseBuilder type(String type) {
+ return delegate.type(type);
+ }
+
+ @Override
+ public Response.ResponseBuilder variant(Variant variant) {
+ return delegate.variant(variant);
+ }
+
+ @Override
+ public Response.ResponseBuilder contentLocation(java.net.URI location) {
+ return delegate.contentLocation(location);
+ }
+
+ @Override
+ public Response.ResponseBuilder cookie(NewCookie... cookies) {
+ return delegate.cookie(cookies);
+ }
+
+ @Override
+ public Response.ResponseBuilder expires(Date expires) {
+ return delegate.expires(expires);
+ }
+
+ @Override
+ public Response.ResponseBuilder lastModified(Date lastModified) {
+ return delegate.lastModified(lastModified);
+ }
+
+ @Override
+ public Response.ResponseBuilder location(java.net.URI location) {
+ return delegate.location(location);
+ }
+
+ @Override
+ public Response.ResponseBuilder tag(EntityTag tag) {
+ return delegate.tag(tag);
+ }
+
+ @Override
+ public Response.ResponseBuilder tag(String tag) {
+ return delegate.tag(tag);
+ }
+
+ @Override
+ public Response.ResponseBuilder variants(Variant... variants) {
+ return delegate.variants(variants);
+ }
+
+ @Override
+ public Response.ResponseBuilder variants(List<Variant> variants) {
+ return delegate.variants(variants);
+ }
+
+ @Override
+ public Response.ResponseBuilder links(Link... links) {
+ return delegate.links(links);
+ }
+
+ @Override
+ public Response.ResponseBuilder link(java.net.URI uri, String rel) {
+ return delegate.link(uri, rel);
+ }
+
+ @Override
+ public Response.ResponseBuilder link(String uri, String rel) {
+ return delegate.link(uri, rel);
+ }
+
+ public RB(Response.ResponseBuilder delegate) {
+ this.delegate = delegate;
+ }
+
+ }
}