diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuilder.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuilder.java index 7738f79ab..7b2459225 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuilder.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuilder.java @@ -20,30 +20,69 @@ import java.net.URI; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.rest.core.mapping.ResourceMetadata; import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkBuilder; import org.springframework.hateoas.core.LinkBuilderSupport; +import org.springframework.util.Assert; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder; +/** + * {@link LinkBuilder} to be able to create links pointing to repositories. + * + * @author Oliver Gierke + */ public class RepositoryLinkBuilder extends LinkBuilderSupport { private final ResourceMetadata metadata; + /** + * Creates a new {@link RepositoryLinkBuilder} with the given {@link ResourceMetadata} and base {@link URI}. + * + * @param metadata must not be {@literal null}. + * @param baseUri + */ public RepositoryLinkBuilder(ResourceMetadata metadata, URI baseUri) { this(metadata, prepareBuilder(baseUri, metadata)); } + /** + * Creates a new {@link RepositoryLinkBuilder} with the given {@link ResourceMetadata} and + * {@link UriComponentsBuilder}. + * + * @param metadata must not be {@literal null}. + * @param builder must not be {@literal null}. + */ private RepositoryLinkBuilder(ResourceMetadata metadata, UriComponentsBuilder builder) { super(builder); + Assert.notNull(metadata, "ResourceMetadata must not be null!"); this.metadata = metadata; } + /** + * Prepares the {@link UriComponentsBuilder} pointing to the root repository path. If the given URI is an absolute one + * (starting with {@code http://}) we'll use it as is and fallback to lookup the root URI of the current request's + * servlet mapping appending the base URI. + * + * @param baseUri must not be {@literal null}. + * @param metadata must not be {@literal null}. + * @return + */ private static UriComponentsBuilder prepareBuilder(URI baseUri, ResourceMetadata metadata) { - ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentServletMapping(); - return builder.path(baseUri.toString()).path(metadata.getPath().toString()); + Assert.notNull(baseUri, "Base URI must not be null!"); + Assert.notNull(metadata, "ResourceMetadata must not be null!"); + + UriComponentsBuilder builder = baseUri.isAbsolute() ? UriComponentsBuilder.fromUri(baseUri) + : ServletUriComponentsBuilder.fromCurrentServletMapping().path(baseUri.toString()); + + return builder.path(metadata.getPath().toString()); } + /* + * (non-Javadoc) + * @see org.springframework.hateoas.core.LinkBuilderSupport#slash(java.lang.Object) + */ @Override public RepositoryLinkBuilder slash(Object object) { diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuildUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuildUnitTests.java new file mode 100644 index 000000000..b7ae2cdb5 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryLinkBuildUnitTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed 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.springframework.data.rest.webmvc.support; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.net.URI; + +import org.junit.Test; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.rest.core.mapping.MappingResourceMetadata; +import org.springframework.data.rest.core.mapping.ResourceMetadata; +import org.springframework.data.rest.webmvc.WebTestUtils; +import org.springframework.data.rest.webmvc.mongodb.Profile; +import org.springframework.hateoas.Link; + +/** + * Unit tests for {@link RepositoryLinkBuilder}. + * + * @author Oliver Gierke + */ +public class RepositoryLinkBuildUnitTests { + + MongoMappingContext context = new MongoMappingContext(); + + /** + * @see DATAREST-292 + */ + @Test + public void usesCurrentRequestsUriBaseForRelativeBaseUri() { + + WebTestUtils.initWebTest(); + + assertRootUriFor("api", "http://localhost/api/profile"); + } + + /** + * @see DATAREST-292, DATAREST-296 + */ + @Test + public void usesBaseUriOnlyIfItIsAbsolute() { + assertRootUriFor("http://foobar/api", "http://foobar/api/profile"); + } + + private void assertRootUriFor(String baseUri, String expectedUri) { + + MongoPersistentEntity entity = context.getPersistentEntity(Profile.class); + ResourceMetadata metadata = new MappingResourceMetadata(entity); + + RepositoryLinkBuilder builder = new RepositoryLinkBuilder(metadata, URI.create(baseUri)); + Link link = builder.withSelfRel(); + + assertThat(link.getHref(), is(expectedUri)); + } +}