Repository: marmotta Updated Branches: refs/heads/ldp f0b9944fc -> 93caa0f61
MARMOTTA-531: Changed the constrainet relation link (rel="ldp:contrainedBy") MARMOTTA-530: Added context (anchor="...") to rel="describedby" Links MARMOTTA-519, MAROTTA-520: tests pass with the updated ldp-testsuite Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/93caa0f6 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/93caa0f6 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/93caa0f6 Branch: refs/heads/ldp Commit: 93caa0f613ba1978221f621fc541902cd086874a Parents: 5c3fab1 Author: Jakob Frank <[email protected]> Authored: Fri Sep 12 13:10:54 2014 +0200 Committer: Jakob Frank <[email protected]> Committed: Fri Sep 12 13:16:51 2014 +0200 ---------------------------------------------------------------------- .../platform/ldp/util/ResponseBuilderImpl.java | 345 +++++++++++++++++++ .../platform/ldp/webservices/LdpWebService.java | 18 +- 2 files changed, 356 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/93caa0f6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/ResponseBuilderImpl.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/ResponseBuilderImpl.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/ResponseBuilderImpl.java new file mode 100644 index 0000000..3723d14 --- /dev/null +++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/ResponseBuilderImpl.java @@ -0,0 +1,345 @@ +/* + * 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 org.jboss.resteasy.core.Headers; +import org.jboss.resteasy.specimpl.BuiltResponse; +import org.jboss.resteasy.spi.HttpRequest; +import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.jboss.resteasy.util.HeaderHelper; +import org.jboss.resteasy.util.HttpHeaderNames; + +import javax.ws.rs.core.*; +import java.lang.annotation.Annotation; +import java.net.URI; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Shamelessy copied from resteasy-jaxrs until RESTEASY-1106 is fixed. + * <p> + * <i>RESTEASY is Apache-License and does not contain a NOTICE, so for now this should be fine...</i> + * + * @deprecated use {@link javax.ws.rs.core.Response#status(int)} once RESTEASY-1106 is fixed. + */ +@Deprecated +public class ResponseBuilderImpl extends Response.ResponseBuilder { + protected Object entity = null; + protected Annotation[] entityAnnotations; + protected int status = -1; + protected Headers<Object> metadata = new Headers<Object>(); + + public ResponseBuilderImpl(int status) { + this.status = status; + } + + @Override + public Response build() { + if (status == -1 && entity == null) status = 204; + else if (status == -1) status = 200; + return new BuiltResponse(status, metadata, entity, entityAnnotations); + } + + @Override + public Response.ResponseBuilder clone() { + ResponseBuilderImpl impl = new ResponseBuilderImpl(status); + impl.metadata.putAll(metadata); + impl.entity = entity; + impl.entityAnnotations = entityAnnotations; + return impl; + } + + @Override + public Response.ResponseBuilder status(int status) { + this.status = status; + return this; + } + + @Override + public Response.ResponseBuilder entity(Object entity) { + this.entity = entity; + return this; + } + + @Override + public Response.ResponseBuilder entity(Object entity, Annotation[] annotations) { + this.entity = entity; + this.entityAnnotations = annotations; + return this; + } + + @Override + public Response.ResponseBuilder type(MediaType type) { + if (type == null) { + metadata.remove(HttpHeaderNames.CONTENT_TYPE); + return this; + } + metadata.putSingle(HttpHeaderNames.CONTENT_TYPE, type); + return this; + } + + @Override + public Response.ResponseBuilder type(String type) { + if (type == null) { + metadata.remove(HttpHeaderNames.CONTENT_TYPE); + return this; + } + metadata.putSingle(HttpHeaderNames.CONTENT_TYPE, type); + return this; + } + + @Override + public Response.ResponseBuilder variant(Variant variant) { + if (variant == null) { + type((String) null); + language((String) null); + metadata.remove(HttpHeaderNames.CONTENT_ENCODING); + return this; + } + type(variant.getMediaType()); + language(variant.getLanguage()); + if (variant.getEncoding() != null) metadata.putSingle(HttpHeaderNames.CONTENT_ENCODING, variant.getEncoding()); + else metadata.remove(HttpHeaderNames.CONTENT_ENCODING); + return this; + } + + @Override + public Response.ResponseBuilder variants(List<Variant> variants) { + if (variants == null) { + metadata.remove(HttpHeaderNames.VARY); + return this; + } + String vary = createVaryHeader(variants); + metadata.putSingle(HttpHeaderNames.VARY, vary); + + return this; + } + + public static String createVaryHeader(List<Variant> variants) { + boolean accept = false; + boolean acceptLanguage = false; + boolean acceptEncoding = false; + + for (Variant variant : variants) { + if (variant.getMediaType() != null) accept = true; + if (variant.getLanguage() != null) acceptLanguage = true; + if (variant.getEncoding() != null) acceptEncoding = true; + } + + String vary = null; + if (accept) vary = HttpHeaderNames.ACCEPT; + if (acceptLanguage) { + if (vary == null) vary = HttpHeaderNames.ACCEPT_LANGUAGE; + else vary += ", " + HttpHeaderNames.ACCEPT_LANGUAGE; + } + if (acceptEncoding) { + if (vary == null) vary = HttpHeaderNames.ACCEPT_ENCODING; + else vary += ", " + HttpHeaderNames.ACCEPT_ENCODING; + } + return vary; + } + + @Override + public Response.ResponseBuilder language(String language) { + if (language == null) { + metadata.remove(HttpHeaderNames.CONTENT_LANGUAGE); + return this; + } + metadata.putSingle(HttpHeaderNames.CONTENT_LANGUAGE, language); + return this; + } + + @Override + public Response.ResponseBuilder location(URI location) { + if (location == null) { + metadata.remove(HttpHeaderNames.LOCATION); + return this; + } + if (!location.isAbsolute() && ResteasyProviderFactory.getContextData(HttpRequest.class) != null) { + String path = location.toString(); + if (path.startsWith("/")) path = path.substring(1); + URI baseUri = ResteasyProviderFactory.getContextData(HttpRequest.class).getUri().getBaseUri(); + location = baseUri.resolve(path); + } + metadata.putSingle(HttpHeaderNames.LOCATION, location); + return this; + } + + @Override + public Response.ResponseBuilder contentLocation(URI location) { + if (location == null) { + metadata.remove(HttpHeaderNames.CONTENT_LOCATION); + return this; + } + if (!location.isAbsolute() && ResteasyProviderFactory.getContextData(HttpRequest.class) != null) { + String path = location.toString(); + if (path.startsWith("/")) path = path.substring(1); + URI baseUri = ResteasyProviderFactory.getContextData(HttpRequest.class).getUri().getBaseUri(); + location = baseUri.resolve(path); + } + metadata.putSingle(HttpHeaderNames.CONTENT_LOCATION, location); + return this; + } + + @Override + public Response.ResponseBuilder tag(EntityTag tag) { + if (tag == null) { + metadata.remove(HttpHeaderNames.ETAG); + return this; + } + metadata.putSingle(HttpHeaderNames.ETAG, tag); + return this; + } + + @Override + public Response.ResponseBuilder tag(String tag) { + if (tag == null) { + metadata.remove(HttpHeaderNames.ETAG); + return this; + } + metadata.putSingle(HttpHeaderNames.ETAG, tag); + return this; + } + + @Override + public Response.ResponseBuilder lastModified(Date lastModified) { + if (lastModified == null) { + metadata.remove(HttpHeaderNames.LAST_MODIFIED); + return this; + } + metadata.putSingle(HttpHeaderNames.LAST_MODIFIED, lastModified); + return this; + } + + @Override + public Response.ResponseBuilder cacheControl(CacheControl cacheControl) { + if (cacheControl == null) { + metadata.remove(HttpHeaderNames.CACHE_CONTROL); + return this; + } + metadata.putSingle(HttpHeaderNames.CACHE_CONTROL, cacheControl); + return this; + } + + @Override + public Response.ResponseBuilder header(String name, Object value) { + if (value == null) { + metadata.remove(name); + return this; + } + metadata.add(name, value); + return this; + } + + @Override + public Response.ResponseBuilder cookie(NewCookie... cookies) { + if (cookies == null) { + metadata.remove(HttpHeaderNames.SET_COOKIE); + return this; + } + for (NewCookie cookie : cookies) { + metadata.add(HttpHeaderNames.SET_COOKIE, cookie); + } + return this; + } + + public Response.ResponseBuilder language(Locale language) { + if (language == null) { + metadata.remove(HttpHeaderNames.CONTENT_LANGUAGE); + return this; + } + metadata.putSingle(HttpHeaderNames.CONTENT_LANGUAGE, language); + return this; + } + + public static SimpleDateFormat getDateFormatRFC822() { + SimpleDateFormat dateFormatRFC822 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormatRFC822.setTimeZone(TimeZone.getTimeZone("GMT")); + return dateFormatRFC822; + } + + public Response.ResponseBuilder expires(Date expires) { + if (expires == null) { + metadata.remove(HttpHeaderNames.EXPIRES); + return this; + } + metadata.putSingle(HttpHeaderNames.EXPIRES, getDateFormatRFC822().format(expires)); + return this; + } + + public Response.ResponseBuilder allow(String... methods) { + if (methods == null) { + return allow((Set<String>) null); + } + HashSet<String> set = new HashSet<String>(); + for (String m : methods) set.add(m); + return allow(set); + } + + public Response.ResponseBuilder allow(Set<String> methods) { + HeaderHelper.setAllow(this.metadata, methods); + return this; + } + + + @Override + public Response.ResponseBuilder encoding(String encoding) { + if (encoding == null) { + metadata.remove(HttpHeaders.CONTENT_ENCODING); + return this; + } + metadata.putSingle(HttpHeaders.CONTENT_ENCODING, encoding); + return this; + } + + @Override + public Response.ResponseBuilder variants(Variant... variants) { + return this.variants(Arrays.asList(variants)); + } + + @Override + public Response.ResponseBuilder links(Link... links) { + if (links == null) metadata.remove(HttpHeaders.LINK); + else for (Link link : links) { + metadata.add(HttpHeaders.LINK, link); + } + return this; + } + + @Override + public Response.ResponseBuilder link(URI uri, String rel) { + Link link = Link.fromUri(uri).rel(rel).build(); + metadata.add(HttpHeaders.LINK, link); + return this; + } + + @Override + public Response.ResponseBuilder link(String uri, String rel) { + Link link = Link.fromUri(uri).rel(rel).build(); + metadata.add(HttpHeaders.LINK, link); + return this; + } + + @Override + public Response.ResponseBuilder replaceAll(MultivaluedMap<String, Object> headers) { + metadata.clear(); + if (headers == null) return this; + metadata.putAll(headers); + return this; + } + +} http://git-wip-us.apache.org/repos/asf/marmotta/blob/93caa0f6/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 3b23d75..b18f4e3 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 @@ -34,6 +34,7 @@ import org.apache.marmotta.platform.ldp.patch.parser.ParseException; import org.apache.marmotta.platform.ldp.patch.parser.RdfPatchParser; import org.apache.marmotta.platform.ldp.util.EntityTagUtils; import org.apache.marmotta.platform.ldp.util.LdpUtils; +import org.apache.marmotta.platform.ldp.util.ResponseBuilderImpl; import org.jboss.resteasy.spi.NoLogWebApplicationException; import org.openrdf.model.Statement; import org.openrdf.model.URI; @@ -73,10 +74,11 @@ public class LdpWebService { public static final String LDP_SERVER_CONSTRAINTS = "http://wiki.apache.org/marmotta/LDPImplementationReport/2014-03-11"; static final String LINK_REL_DESCRIBEDBY = "describedby"; - static final String LINK_REL_CONSTRAINEDBY = LINK_REL_DESCRIBEDBY; + static final String LINK_REL_CONSTRAINEDBY = "http://www.w3.org/ns/ldp#constrainedBy"; static final String LINK_REL_CONTENT = "content"; static final String LINK_REL_META = "meta"; static final String LINK_REL_TYPE = "type"; + static final String LINK_PARAM_ANCHOR = "anchor"; static final String HTTP_HEADER_SLUG = "Slug"; static final String HTTP_HEADER_ACCEPT_POST = "Accept-Post"; static final String HTTP_HEADER_ACCEPT_PATCH = "Accept-Patch"; @@ -429,7 +431,7 @@ public class LdpWebService { String location = ldpService.addResource(connection, container, newResource, interactionModel, mimeType, requestBody); final Response.ResponseBuilder response = createResponse(connection, Response.Status.CREATED, container).location(java.net.URI.create(location)); if (newResource.compareTo(location) != 0) { - response.link(newResource, LINK_REL_DESCRIBEDBY); //FIXME: Sec. 5.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15 + response.links(Link.fromUri(newResource).rel(LINK_REL_DESCRIBEDBY).param(LINK_PARAM_ANCHOR, location).build()); //FIXME: Sec. 5.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15 } connection.commit(); return response.build(); @@ -490,7 +492,7 @@ public class LdpWebService { conn.commit(); return resp.build(); } else if (ldpService.isReusedURI(conn, resource)) { - log.debug("<{}> has beed deleted, we should not re-use the URI!", resource); + log.debug("<{}> has been deleted, we should not re-use the URI!", resource); resp = createResponse(conn, Response.Status.GONE, resource); conn.commit(); return resp.build(); @@ -706,7 +708,7 @@ public class LdpWebService { * * @param connection the RepositoryConnection (with active transaction) to read extra data from * @param status the StatusCode - * @param resource the iri/uri/url of the resouce + * @param resource the iri/uri/url of the resource * @return the provided ResponseBuilder for chaining */ protected Response.ResponseBuilder createResponse(RepositoryConnection connection, Response.Status status, String resource) throws RepositoryException { @@ -718,11 +720,13 @@ public class LdpWebService { * * @param connection the RepositoryConnection (with active transaction) to read extra data from * @param status the status code - * @param resource the uri/url of the resouce + * @param resource the uri/url of the resource * @return the provided ResponseBuilder for chaining */ protected Response.ResponseBuilder createResponse(RepositoryConnection connection, int status, String resource) throws RepositoryException { - return createResponse(connection, Response.status(status), resource); + // FIXME: Switch back to the general ResponseBuilder (once RESTEASY-1106 is fixed) + // return createResponse(connection, Response.status(status), resource); + return createResponse(connection, new ResponseBuilderImpl(status), resource); } /** @@ -776,7 +780,7 @@ public class LdpWebService { * @return the updated ResponseBuilder for chaining */ protected Response.ResponseBuilder createResponse(Response.ResponseBuilder rb) { - // Link rel='describedby' (Sec. 4.2.1.6) + // Link rel='http://www.w3.org/ns/ldp#constrainedBy' (Sec. 4.2.1.6) rb.link(LDP_SERVER_CONSTRAINTS, LINK_REL_CONSTRAINEDBY); return rb;
