Java tutorial
/* * Copyright 2012-2017 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 io.spring.initializr.web; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadataBuilder; import io.spring.initializr.metadata.InitializrMetadataProvider; import io.spring.initializr.metadata.InitializrProperties; import io.spring.initializr.test.generator.ProjectAssert; import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config; import io.spring.initializr.web.mapper.InitializrMetadataVersion; import io.spring.initializr.web.support.DefaultInitializrMetadataProvider; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Expand; import org.apache.tools.ant.taskdefs.Untar; import org.json.JSONObject; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StreamUtils; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertTrue; /** * @author Stephane Nicoll */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Config.class) public abstract class AbstractInitializrIntegrationTests { protected static final MediaType CURRENT_METADATA_MEDIA_TYPE = InitializrMetadataVersion.V2_1.getMediaType(); @Rule public final TemporaryFolder folder = new TemporaryFolder(); @Autowired private RestTemplateBuilder restTemplateBuilder; private RestTemplate restTemplate; @Before public void before() { restTemplate = restTemplateBuilder.build(); } protected abstract String createUrl(String context); protected String htmlHome() { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.TEXT_HTML)); return restTemplate.exchange(createUrl("/"), HttpMethod.GET, new HttpEntity<Void>(headers), String.class) .getBody(); } /** * Validate the "Content-Type" header of the specified response. */ protected void validateContentType(ResponseEntity<String> response, MediaType expected) { MediaType actual = response.getHeaders().getContentType(); assertTrue("Non compatible media-type, expected " + expected + ", got " + actual, actual.isCompatibleWith(expected)); } protected void validateMetadata(ResponseEntity<String> response, MediaType mediaType, String version, JSONCompareMode compareMode) { validateContentType(response, mediaType); JSONObject json = new JSONObject(response.getBody()); JSONObject expected = readMetadataJson(version); JSONAssert.assertEquals(expected, json, compareMode); } protected void validateCurrentMetadata(ResponseEntity<String> response) { validateContentType(response, CURRENT_METADATA_MEDIA_TYPE); validateCurrentMetadata(new JSONObject(response.getBody())); } protected void validateCurrentMetadata(JSONObject json) { JSONObject expected = readMetadataJson("2.1.0"); JSONAssert.assertEquals(expected, json, JSONCompareMode.STRICT); } private JSONObject readMetadataJson(String version) { return readJsonFrom("metadata/test-default-" + version + ".json"); } /** * Return a {@link ProjectAssert} for the following archive content. */ protected ProjectAssert zipProjectAssert(byte[] content) { return projectAssert(content, ArchiveType.ZIP); } /** * Return a {@link ProjectAssert} for the following TGZ archive. */ protected ProjectAssert tgzProjectAssert(byte[] content) { return projectAssert(content, ArchiveType.TGZ); } protected ProjectAssert downloadZip(String context) { byte[] body = downloadArchive(context); return zipProjectAssert(body); } protected ProjectAssert downloadTgz(String context) { byte[] body = downloadArchive(context); return tgzProjectAssert(body); } protected byte[] downloadArchive(String context) { return restTemplate.getForObject(createUrl(context), byte[].class); } protected ResponseEntity<String> invokeHome(String userAgentHeader, String... acceptHeaders) { return execute("/", String.class, userAgentHeader, acceptHeaders); } protected <T> ResponseEntity<T> execute(String contextPath, Class<T> responseType, String userAgentHeader, String... acceptHeaders) { HttpHeaders headers = new HttpHeaders(); if (userAgentHeader != null) { headers.set("User-Agent", userAgentHeader); } if (acceptHeaders != null) { List<MediaType> mediaTypes = new ArrayList<>(); for (String acceptHeader : acceptHeaders) { mediaTypes.add(MediaType.parseMediaType(acceptHeader)); } headers.setAccept(mediaTypes); } else { headers.setAccept(Collections.emptyList()); } return restTemplate.exchange(createUrl(contextPath), HttpMethod.GET, new HttpEntity<Void>(headers), responseType); } protected ProjectAssert projectAssert(byte[] content, ArchiveType archiveType) { try { File archiveFile = writeArchive(content); File project = folder.newFolder(); switch (archiveType) { case ZIP: unzip(archiveFile, project); break; case TGZ: untar(archiveFile, project); break; } return new ProjectAssert(project); } catch (Exception e) { throw new IllegalStateException("Cannot unpack archive", e); } } private void untar(File archiveFile, File project) { Untar expand = new Untar(); expand.setProject(new Project()); expand.setDest(project); expand.setSrc(archiveFile); Untar.UntarCompressionMethod method = new Untar.UntarCompressionMethod(); method.setValue("gzip"); expand.setCompression(method); expand.execute(); } private void unzip(File archiveFile, File project) { Expand expand = new Expand(); expand.setProject(new Project()); expand.setDest(project); expand.setSrc(archiveFile); expand.execute(); } protected File writeArchive(byte[] body) throws IOException { File archiveFile = folder.newFile(); try (FileOutputStream stream = new FileOutputStream(archiveFile)) { stream.write(body); } return archiveFile; } protected JSONObject readJsonFrom(String path) { try { ClassPathResource resource = new ClassPathResource(path); try (InputStream stream = resource.getInputStream()) { String json = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); String placeholder = ""; if (this instanceof AbstractInitializrControllerIntegrationTests) { placeholder = ((AbstractInitializrControllerIntegrationTests) this).host; } if (this instanceof AbstractFullStackInitializrIntegrationTests) { AbstractFullStackInitializrIntegrationTests test = (AbstractFullStackInitializrIntegrationTests) this; placeholder = test.host + ":" + test.port; } // Let's parse the port as it is random // TODO: put the port back somehow so it appears in stubs String content = json.replaceAll("@host@", placeholder); return new JSONObject(content); } } catch (Exception e) { throw new IllegalStateException("Cannot read JSON from path=" + path); } } public RestTemplate getRestTemplate() { return restTemplate; } private enum ArchiveType { ZIP, TGZ } @EnableAutoConfiguration public static class Config { @Bean public InitializrMetadataProvider initializrMetadataProvider(InitializrProperties properties) { return new DefaultInitializrMetadataProvider( InitializrMetadataBuilder.fromInitializrProperties(properties).build(), new RestTemplate()) { @Override protected void updateInitializrMetadata(InitializrMetadata metadata) { // Disable metadata fetching from spring.io } }; } } }