/* * 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 org.springframework.boot.context.embedded; import java.io.File; import java.io.FileReader; import java.lang.ProcessBuilder.Redirect; import java.util.ArrayList; import java.util.List; import org.junit.rules.ExternalResource; import org.springframework.util.FileCopyUtils; /** * Base {@link ExternalResource} for launching a Spring Boot application as part of a * JUnit test. * * @author Andy Wilkinson */ abstract class AbstractApplicationLauncher extends ExternalResource { private final ApplicationBuilder applicationBuilder; private Process process; private int httpPort; protected AbstractApplicationLauncher(ApplicationBuilder applicationBuilder) { this.applicationBuilder = applicationBuilder; } @Override protected final void before() throws Throwable { this.process = startApplication(); } @Override protected final void after() { this.process.destroy(); } public final int getHttpPort() { return this.httpPort; } protected abstract List<String> getArguments(File archive); protected abstract File getWorkingDirectory(); protected abstract String getDescription(String packaging); private Process startApplication() throws Exception { File workingDirectory = getWorkingDirectory(); File serverPortFile = workingDirectory == null ? new File("target/server.port") : new File(workingDirectory, "target/server.port"); serverPortFile.delete(); File archive = this.applicationBuilder.buildApplication(); List<String> arguments = new ArrayList<>(); arguments.add(System.getProperty("java.home") + "/bin/java"); arguments.addAll(getArguments(archive)); ProcessBuilder processBuilder = new ProcessBuilder( arguments.toArray(new String[arguments.size()])); processBuilder.redirectOutput(Redirect.INHERIT); processBuilder.redirectError(Redirect.INHERIT); if (workingDirectory != null) { processBuilder.directory(workingDirectory); } Process process = processBuilder.start(); this.httpPort = awaitServerPort(process, serverPortFile); return process; } private int awaitServerPort(Process process, File serverPortFile) throws Exception { long end = System.currentTimeMillis() + 30000; while (serverPortFile.length() == 0) { if (System.currentTimeMillis() > end) { throw new IllegalStateException( "server.port file was not written within 30 seconds"); } if (!process.isAlive()) { throw new IllegalStateException("Application failed to launch"); } Thread.sleep(100); } return Integer .parseInt(FileCopyUtils.copyToString(new FileReader(serverPortFile))); } }