diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle deleted file mode 100644 index 37902735bdd..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version-spring-boot}' -} - -tasks.named("bootJar") { - mainClass = 'com.example.ExampleApplication' -} - -// tag::custom-launch-script[] -tasks.named("bootJar") { - launchScript { - script = file('src/custom.script') - } -} -// end::custom-launch-script[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle.kts b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle.kts deleted file mode 100644 index daeba8a2360..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-custom-launch-script.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -import org.springframework.boot.gradle.tasks.bundling.BootJar - -plugins { - java - id("org.springframework.boot") version "{version-spring-boot}" -} - -tasks.named("bootJar") { - mainClass.set("com.example.ExampleApplication") -} - -// tag::custom-launch-script[] -tasks.named("bootJar") { - launchScript { - script = file("src/custom.script") - } -} -// end::custom-launch-script[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle deleted file mode 100644 index c893b5a2f03..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version-spring-boot}' -} - -tasks.named("bootJar") { - mainClass = 'com.example.ExampleApplication' -} - -// tag::include-launch-script[] -tasks.named("bootJar") { - launchScript() -} -// end::include-launch-script[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle.kts b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle.kts deleted file mode 100644 index fa10543b373..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-include-launch-script.gradle.kts +++ /dev/null @@ -1,16 +0,0 @@ -import org.springframework.boot.gradle.tasks.bundling.BootJar - -plugins { - java - id("org.springframework.boot") version "{version-spring-boot}" -} - -tasks.named("bootJar") { - mainClass.set("com.example.ExampleApplication") -} - -// tag::include-launch-script[] -tasks.named("bootJar") { - launchScript() -} -// end::include-launch-script[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle deleted file mode 100644 index 2c3980b3629..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version-spring-boot}' -} - -tasks.named("bootJar") { - mainClass = 'com.example.ExampleApplication' -} - -// tag::launch-script-properties[] -tasks.named("bootJar") { - launchScript { - properties 'logFilename': 'example-app.log' - } -} -// end::launch-script-properties[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle.kts b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle.kts deleted file mode 100644 index ec549aebd5b..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/examples/packaging/boot-jar-launch-script-properties.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -import org.springframework.boot.gradle.tasks.bundling.BootJar - -plugins { - java - id("org.springframework.boot") version "{version-spring-boot}" -} - -tasks.named("bootJar") { - mainClass.set("com.example.ExampleApplication") -} - -// tag::launch-script-properties[] -tasks.named("bootJar") { - launchScript { - properties(mapOf("logFilename" to "example-app.log")) - } -} -// end::launch-script-properties[] diff --git a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/pages/packaging.adoc b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/pages/packaging.adoc index 86a13d1761f..fa7aa67dbdf 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/pages/packaging.adoc +++ b/build-plugin/spring-boot-gradle-plugin/src/docs/antora/modules/gradle-plugin/pages/packaging.adoc @@ -246,75 +246,6 @@ The closure is passed a `FileTreeElement` and should return a `boolean` indicati -[[packaging-executable.configuring.launch-script]] -=== Making an Archive Fully Executable - -Spring Boot provides support for fully executable archives. -An archive is made fully executable by prepending a shell script that knows how to launch the application. -On Unix-like platforms, this launch script allows the archive to be run directly like any other executable or to be installed as a service. - -NOTE: Currently, some tools do not accept this format so you may not always be able to use this technique. -For example, `jar -xf` may silently fail to extract a jar or war that has been made fully-executable. -It is recommended that you only enable this option if you intend to execute it directly, rather than running it with `java -jar` or deploying it to a servlet container. - -To use this feature, the inclusion of the launch script must be enabled: - -[tabs] -====== -Groovy:: -+ -[source,groovy,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-include-launch-script.gradle[tags=include-launch-script] ----- -Kotlin:: -+ -[source,kotlin,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-include-launch-script.gradle.kts[tags=include-launch-script] ----- -====== - -This will add Spring Boot's default launch script to the archive. -The default launch script includes several properties with sensible default values. -The values can be customized using the `properties` property: - -[tabs] -====== -Groovy:: -+ -[source,groovy,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-launch-script-properties.gradle[tags=launch-script-properties] ----- -Kotlin:: -+ -[source,kotlin,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-launch-script-properties.gradle.kts[tags=launch-script-properties] ----- -====== - -If the default launch script does not meet your needs, the `script` property can be used to provide a custom launch script: - -[tabs] -====== -Groovy:: -+ -[source,groovy,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-custom-launch-script.gradle[tags=custom-launch-script] ----- -Kotlin:: -+ -[source,kotlin,indent=0,subs="verbatim,attributes"] ----- -include::example$packaging/boot-jar-custom-launch-script.gradle.kts[tags=custom-launch-script] ----- -====== - - - [[packaging-executable.configuring.properties-launcher]] === Using the PropertiesLauncher diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchive.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchive.java index deeadcb9a00..277df65a059 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchive.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchive.java @@ -18,7 +18,6 @@ package org.springframework.boot.gradle.tasks.bundling; import java.util.Set; -import org.gradle.api.Action; import org.gradle.api.JavaVersion; import org.gradle.api.Project; import org.gradle.api.Task; @@ -30,7 +29,6 @@ import org.gradle.api.provider.Provider; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.Optional; import org.jspecify.annotations.Nullable; @@ -65,28 +63,6 @@ public interface BootArchive extends Task { */ void requiresUnpack(Spec spec); - /** - * Returns the {@link LaunchScriptConfiguration} that will control the script that is - * prepended to the archive. - * @return the launch script configuration, or {@code null} if the launch script has - * not been configured. - */ - @Nested - @Optional - @Nullable LaunchScriptConfiguration getLaunchScript(); - - /** - * Configures the archive to have a prepended launch script. - */ - void launchScript(); - - /** - * Configures the archive to have a prepended launch script, customizing its - * configuration using the given {@code action}. - * @param action the action to apply - */ - void launchScript(Action action); - /** * Returns the classpath that will be included in the archive. * @return the classpath diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java index 9597ab3cc74..0689e1afb4c 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java @@ -75,8 +75,6 @@ class BootArchiveSupport { private final Function compressionResolver; - private @Nullable LaunchScriptConfiguration launchScript; - BootArchiveSupport(String loaderMainClass, Spec librarySpec, Function compressionResolver) { this.loaderMainClass = loaderMainClass; @@ -129,13 +127,12 @@ class BootArchiveSupport { boolean includeDefaultLoader = isUsingDefaultLoader(jar); Spec requiresUnpack = this.requiresUnpack.getAsSpec(); Spec exclusions = this.exclusions.getAsExcludeSpec(); - LaunchScriptConfiguration launchScript = this.launchScript; Spec librarySpec = this.librarySpec; Function compressionResolver = this.compressionResolver; String encoding = jar.getMetadataCharset(); CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions, - filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript, - librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver); + filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, librarySpec, + compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver); return action; } @@ -175,14 +172,6 @@ class BootArchiveSupport { return DEFAULT_LAUNCHER_CLASSES.contains(jar.getManifest().getAttributes().get("Main-Class")); } - @Nullable LaunchScriptConfiguration getLaunchScript() { - return this.launchScript; - } - - void setLaunchScript(LaunchScriptConfiguration launchScript) { - this.launchScript = launchScript; - } - void requiresUnpack(String... patterns) { this.requiresUnpack.include(patterns); } diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java index 5e3ad8f2362..25ee5a2d795 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java @@ -166,21 +166,6 @@ public abstract class BootJar extends Jar implements BootArchive { this.support.requiresUnpack(spec); } - @Override - public @Nullable LaunchScriptConfiguration getLaunchScript() { - return this.support.getLaunchScript(); - } - - @Override - public void launchScript() { - enableLaunchScriptIfNecessary(); - } - - @Override - public void launchScript(Action action) { - action.execute(enableLaunchScriptIfNecessary()); - } - /** * Returns the spec that describes the layers in a layered jar. * @return the spec for the layers @@ -273,15 +258,6 @@ public abstract class BootJar extends Jar implements BootArchive { return path.startsWith(LIB_DIRECTORY); } - private LaunchScriptConfiguration enableLaunchScriptIfNecessary() { - LaunchScriptConfiguration launchScript = this.support.getLaunchScript(); - if (launchScript == null) { - launchScript = new LaunchScriptConfiguration(this); - this.support.setLaunchScript(launchScript); - } - return launchScript; - } - /** * Syntactic sugar that makes {@link CopySpec#into} calls a little easier to read. * @param the result type diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java index 970f25335f8..4b9c5ba4f66 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java @@ -140,21 +140,6 @@ public abstract class BootWar extends War implements BootArchive { this.support.requiresUnpack(spec); } - @Override - public @Nullable LaunchScriptConfiguration getLaunchScript() { - return this.support.getLaunchScript(); - } - - @Override - public void launchScript() { - enableLaunchScriptIfNecessary(); - } - - @Override - public void launchScript(Action action) { - action.execute(enableLaunchScriptIfNecessary()); - } - /** * Returns the provided classpath, the contents of which will be included in the * {@code WEB-INF/lib-provided} directory of the war. @@ -241,15 +226,6 @@ public abstract class BootWar extends War implements BootArchive { return path.startsWith(LIB_DIRECTORY) || path.startsWith(LIB_PROVIDED_DIRECTORY); } - private LaunchScriptConfiguration enableLaunchScriptIfNecessary() { - LaunchScriptConfiguration launchScript = this.support.getLaunchScript(); - if (launchScript == null) { - launchScript = new LaunchScriptConfiguration(this); - this.support.setLaunchScript(launchScript); - } - return launchScript; - } - /** * Syntactic sugar that makes {@link CopySpec#into} calls a little easier to read. * @param the result type diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java index c4735b578c0..e799d139739 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java @@ -54,7 +54,6 @@ import org.gradle.util.GradleVersion; import org.jspecify.annotations.Nullable; import org.springframework.boot.gradle.tasks.bundling.ResolvedDependencies.DependencyDescriptor; -import org.springframework.boot.loader.tools.DefaultLaunchScript; import org.springframework.boot.loader.tools.FileUtils; import org.springframework.boot.loader.tools.JarModeLibrary; import org.springframework.boot.loader.tools.Layer; @@ -102,8 +101,6 @@ class BootZipCopyAction implements CopyAction { private final Spec exclusions; - private final @Nullable LaunchScriptConfiguration launchScript; - private final Spec librarySpec; private final Function compressionResolver; @@ -118,8 +115,7 @@ class BootZipCopyAction implements CopyAction { BootZipCopyAction(File output, Manifest manifest, boolean preserveFileTimestamps, @Nullable Integer dirMode, @Nullable Integer fileMode, boolean includeDefaultLoader, @Nullable String jarmodeToolsLocation, - Spec requiresUnpack, Spec exclusions, - @Nullable LaunchScriptConfiguration launchScript, Spec librarySpec, + Spec requiresUnpack, Spec exclusions, Spec librarySpec, Function compressionResolver, @Nullable String encoding, ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile, @Nullable LayerResolver layerResolver) { @@ -132,7 +128,6 @@ class BootZipCopyAction implements CopyAction { this.jarmodeToolsLocation = jarmodeToolsLocation; this.requiresUnpack = requiresUnpack; this.exclusions = exclusions; - this.launchScript = launchScript; this.librarySpec = librarySpec; this.compressionResolver = compressionResolver; this.encoding = encoding; @@ -164,7 +159,6 @@ class BootZipCopyAction implements CopyAction { private void writeArchive(CopyActionProcessingStream copyActions, OutputStream output) throws IOException { ZipArchiveOutputStream zipOutput = new ZipArchiveOutputStream(output); - writeLaunchScriptIfNecessary(zipOutput); try { setEncodingIfNecessary(zipOutput); Processor processor = new Processor(zipOutput); @@ -176,21 +170,6 @@ class BootZipCopyAction implements CopyAction { } } - private void writeLaunchScriptIfNecessary(ZipArchiveOutputStream outputStream) { - if (this.launchScript == null) { - return; - } - try { - File file = this.launchScript.getScript(); - Map properties = this.launchScript.getProperties(); - outputStream.writePreamble(new DefaultLaunchScript(file, properties).toByteArray()); - this.output.setExecutable(true); - } - catch (IOException ex) { - throw new GradleException("Failed to write launch script to " + this.output, ex); - } - } - private void setEncodingIfNecessary(ZipArchiveOutputStream zipOutputStream) { if (this.encoding != null) { zipOutputStream.setEncoding(this.encoding); diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfiguration.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfiguration.java deleted file mode 100644 index b814f67c46d..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfiguration.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.gradle.tasks.bundling; - -import java.io.File; -import java.io.Serializable; -import java.util.Map; -import java.util.TreeMap; -import java.util.regex.Pattern; - -import org.gradle.api.Project; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputFile; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.bundling.AbstractArchiveTask; -import org.jspecify.annotations.Nullable; - -import org.springframework.lang.Contract; -import org.springframework.util.StringUtils; - -/** - * Encapsulates the configuration of the launch script for an executable jar or war. - * - * @author Andy Wilkinson - * @since 2.0.0 - */ -@SuppressWarnings("serial") -public class LaunchScriptConfiguration implements Serializable { - - private static final Pattern WHITE_SPACE_PATTERN = Pattern.compile("\\s+"); - - private static final Pattern LINE_FEED_PATTERN = Pattern.compile("\n"); - - // We don't care about the order, but Gradle's configuration cache currently does. - // https://github.com/gradle/gradle/pull/17863 - private final Map properties = new TreeMap<>(); - - private @Nullable File script; - - public LaunchScriptConfiguration() { - } - - LaunchScriptConfiguration(AbstractArchiveTask archiveTask) { - Project project = archiveTask.getProject(); - String baseName = archiveTask.getArchiveBaseName().get(); - putIfMissing(this.properties, "initInfoProvides", baseName); - putIfMissing(this.properties, "initInfoShortDescription", removeLineBreaks(project.getDescription()), baseName); - putIfMissing(this.properties, "initInfoDescription", augmentLineBreaks(project.getDescription()), baseName); - } - - /** - * Returns the properties that are applied to the launch script when it's being - * including in the executable archive. - * @return the properties - */ - @Input - public Map getProperties() { - return this.properties; - } - - /** - * Sets the properties that are applied to the launch script when it's being including - * in the executable archive. - * @param properties the properties - */ - public void properties(Map properties) { - this.properties.putAll(properties); - } - - /** - * Returns the script {@link File} that will be included in the executable archive. - * When {@code null}, the default launch script will be used. - * @return the script file - */ - @Optional - @InputFile - @PathSensitive(PathSensitivity.RELATIVE) - public @Nullable File getScript() { - return this.script; - } - - /** - * Sets the script {@link File} that will be included in the executable archive. When - * {@code null}, the default launch script will be used. - * @param script the script file - */ - public void setScript(@Nullable File script) { - this.script = script; - } - - @Contract("!null -> !null") - private @Nullable String removeLineBreaks(@Nullable String string) { - return (string != null) ? WHITE_SPACE_PATTERN.matcher(string).replaceAll(" ") : null; - } - - @Contract("!null -> !null") - private @Nullable String augmentLineBreaks(@Nullable String string) { - return (string != null) ? LINE_FEED_PATTERN.matcher(string).replaceAll("\n# ") : null; - } - - private void putIfMissing(Map properties, String key, @Nullable String... valueCandidates) { - if (!properties.containsKey(key)) { - for (String candidate : valueCandidates) { - if (StringUtils.hasLength(candidate)) { - properties.put(key, candidate); - return; - } - } - } - } - -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java index 5cfb93fc620..cdcb297acc1 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java @@ -18,8 +18,6 @@ package org.springframework.boot.gradle.docs; import java.io.File; import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; import java.util.Collections; import java.util.jar.JarEntry; @@ -34,7 +32,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleMultiDslExtension; import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; -import org.springframework.util.FileCopyUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -128,36 +125,6 @@ class PackagingDocumentationTests { } } - @TestTemplate - void bootJarIncludeLaunchScript() throws IOException { - this.gradleBuild.script(Examples.DIR + "packaging/boot-jar-include-launch-script").build("bootJar"); - File file = new File(this.gradleBuild.getProjectDir(), - "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); - assertThat(file).isFile(); - assertThat(FileCopyUtils.copyToString(new FileReader(file))).startsWith("#!/bin/bash"); - } - - @TestTemplate - void bootJarLaunchScriptProperties() throws IOException { - this.gradleBuild.script(Examples.DIR + "packaging/boot-jar-launch-script-properties").build("bootJar"); - File file = new File(this.gradleBuild.getProjectDir(), - "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); - assertThat(file).isFile(); - assertThat(FileCopyUtils.copyToString(new FileReader(file))).contains("example-app.log"); - } - - @TestTemplate - void bootJarCustomLaunchScript() throws IOException { - File customScriptFile = new File(this.gradleBuild.getProjectDir(), "src/custom.script"); - customScriptFile.getParentFile().mkdirs(); - FileCopyUtils.copy("custom", new FileWriter(customScriptFile)); - this.gradleBuild.script(Examples.DIR + "packaging/boot-jar-custom-launch-script").build("bootJar"); - File file = new File(this.gradleBuild.getProjectDir(), - "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); - assertThat(file).isFile(); - assertThat(FileCopyUtils.copyToString(new FileReader(file))).startsWith("custom"); - } - @TestTemplate void bootWarPropertiesLauncher() throws IOException { this.gradleBuild.script(Examples.DIR + "packaging/boot-war-properties-launcher").build("bootWar"); diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java index c151624d732..5d3de661347 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java @@ -123,56 +123,6 @@ abstract class AbstractBootArchiveIntegrationTests { assertThat(task.getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE); } - @TestTemplate - void upToDateWhenBuiltTwiceWithLaunchScriptIncluded() { - BuildTask task = this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName).task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - task = this.gradleBuild.build("-PincludeLaunchScript=true", this.taskName).task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE); - } - - @TestTemplate - void notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded() { - BuildTask task = this.gradleBuild.scriptProperty("launchScript", "") - .build(this.taskName) - .task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - task = this.gradleBuild.scriptProperty("launchScript", "launchScript()") - .build(this.taskName) - .task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - } - - @TestTemplate - void notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded() { - BuildTask task = this.gradleBuild.scriptProperty("launchScript", "launchScript()") - .build(this.taskName) - .task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - task = this.gradleBuild.scriptProperty("launchScript", "").build(this.taskName).task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - } - - @TestTemplate - void notUpToDateWhenLaunchScriptPropertyChanges() { - BuildTask task = this.gradleBuild.scriptProperty("launchScriptProperty", "alpha") - .build(this.taskName) - .task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - task = this.gradleBuild.scriptProperty("launchScriptProperty", "bravo") - .build(this.taskName) - .task(":" + this.taskName); - assertThat(task).isNotNull(); - assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - } - @TestTemplate void applicationPluginMainClassNameIsUsed() throws IOException { BuildTask task = this.gradleBuild.build(this.taskName).task(":" + this.taskName); diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java index 520b2412279..5ab4e610a86 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java @@ -23,18 +23,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.nio.file.attribute.PosixFilePermission; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Enumeration; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.UUID; @@ -66,7 +60,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.gradle.junit.GradleProjectBuilder; -import org.springframework.boot.loader.tools.DefaultLaunchScript; import org.springframework.boot.loader.tools.JarModeLibrary; import org.springframework.util.FileCopyUtils; @@ -310,57 +303,6 @@ abstract class AbstractBootArchiveTests { } } - @Test - void launchScriptCanBePrepended() throws IOException { - this.task.getMainClass().set("com.example.Main"); - this.task.launchScript(); - executeTask(); - Map properties = new HashMap<>(); - properties.put("initInfoProvides", this.task.getArchiveBaseName().get()); - properties.put("initInfoShortDescription", this.project.getDescription()); - properties.put("initInfoDescription", this.project.getDescription()); - File archiveFile = this.task.getArchiveFile().get().getAsFile(); - assertThat(Files.readAllBytes(archiveFile.toPath())) - .startsWith(new DefaultLaunchScript(null, properties).toByteArray()); - try (ZipFile zipFile = ZipFile.builder().setFile(archiveFile).get()) { - assertThat(zipFile.getEntries().hasMoreElements()).isTrue(); - } - try { - Set permissions = Files.getPosixFilePermissions(archiveFile.toPath()); - assertThat(permissions).contains(PosixFilePermission.OWNER_EXECUTE); - } - catch (UnsupportedOperationException ex) { - // Windows, presumably. Continue - } - } - - @Test - void customLaunchScriptCanBePrepended() throws IOException { - this.task.getMainClass().set("com.example.Main"); - File customScript = new File(this.temp, "custom.script"); - Files.writeString(customScript.toPath(), "custom script", StandardOpenOption.CREATE); - this.task.launchScript((configuration) -> configuration.setScript(customScript)); - executeTask(); - Path path = this.task.getArchiveFile().get().getAsFile().toPath(); - assertThat(Files.readString(path, StandardCharsets.ISO_8859_1)).startsWith("custom script"); - } - - @Test - void launchScriptInitInfoPropertiesCanBeCustomized() throws IOException { - this.task.getMainClass().set("com.example.Main"); - this.task.launchScript((configuration) -> { - configuration.getProperties().put("initInfoProvides", "provides"); - configuration.getProperties().put("initInfoShortDescription", "short description"); - configuration.getProperties().put("initInfoDescription", "description"); - }); - executeTask(); - Path path = this.task.getArchiveFile().get().getAsFile().toPath(); - String content = Files.readString(path, StandardCharsets.ISO_8859_1); - assertThat(content).containsSequence("Provides: provides"); - assertThat(content).containsSequence("Short-Description: short description"); - assertThat(content).containsSequence("Description: description"); - } - @Test void customMainClassInTheManifestIsHonored() throws IOException { this.task.getMainClass().set("com.example.Main"); diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfigurationTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfigurationTests.java deleted file mode 100644 index 511ecc13247..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/LaunchScriptConfigurationTests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.gradle.tasks.bundling; - -import org.gradle.api.Project; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.bundling.AbstractArchiveTask; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link LaunchScriptConfiguration}. - * - * @author Andy Wilkinson - */ -class LaunchScriptConfigurationTests { - - private final AbstractArchiveTask task = mock(AbstractArchiveTask.class); - - private final Project project = mock(Project.class); - - @BeforeEach - void setUp() { - given(this.task.getProject()).willReturn(this.project); - } - - @Test - void initInfoProvidesUsesArchiveBaseNameByDefault() { - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoProvides", - "base-name"); - } - - @Test - void initInfoShortDescriptionUsesDescriptionByDefault() { - given(this.project.getDescription()).willReturn("Project description"); - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoShortDescription", - "Project description"); - } - - @Test - void initInfoShortDescriptionUsesArchiveBaseNameWhenDescriptionIsNull() { - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoShortDescription", - "base-name"); - } - - @Test - void initInfoShortDescriptionUsesSingleLineVersionOfMultiLineProjectDescription() { - given(this.project.getDescription()).willReturn("Project\ndescription"); - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoShortDescription", - "Project description"); - } - - @Test - void initInfoDescriptionUsesArchiveBaseNameWhenDescriptionIsNull() { - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoDescription", - "base-name"); - } - - @Test - void initInfoDescriptionUsesProjectDescriptionByDefault() { - given(this.project.getDescription()).willReturn("Project description"); - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoDescription", - "Project description"); - } - - @Test - void initInfoDescriptionUsesCorrectlyFormattedMultiLineProjectDescription() { - given(this.project.getDescription()).willReturn("The\nproject\ndescription"); - Property baseName = stringProperty("base-name"); - given(this.task.getArchiveBaseName()).willReturn(baseName); - assertThat(new LaunchScriptConfiguration(this.task).getProperties()).containsEntry("initInfoDescription", - "The\n# project\n# description"); - } - - @SuppressWarnings("unchecked") - private Property stringProperty(String value) { - Property property = mock(Property.class); - given(property.get()).willReturn(value); - return property; - } - -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/PluginClasspathGradleBuild.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/PluginClasspathGradleBuild.java index 2653b0ef506..44773ac22a6 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/PluginClasspathGradleBuild.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/testkit/PluginClasspathGradleBuild.java @@ -41,7 +41,7 @@ import tools.jackson.databind.JacksonModule; import org.springframework.asm.ClassVisitor; import org.springframework.boot.buildpack.platform.build.BuildRequest; -import org.springframework.boot.loader.tools.LaunchScript; +import org.springframework.boot.loader.tools.Layers; import org.springframework.boot.testsupport.BuildOutput; import org.springframework.boot.testsupport.gradle.testkit.Dsl; import org.springframework.boot.testsupport.gradle.testkit.GradleBuild; @@ -80,7 +80,7 @@ public class PluginClasspathGradleBuild extends GradleBuild { classpath.add(new File("bin/main")); classpath.add(new File("build/classes/java/main")); classpath.add(new File("build/resources/main")); - classpath.add(new File(pathOfJarContaining(LaunchScript.class))); + classpath.add(new File(pathOfJarContaining(Layers.class))); classpath.add(new File(pathOfJarContaining(ClassVisitor.class))); classpath.add(new File(pathOfJarContaining(DependencyManagementPlugin.class))); if (this.kotlin) { diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle deleted file mode 100644 index ba93c2a4a9c..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version}' -} - -bootJar { - mainClass = 'com.example.Application' - launchScript { - properties 'prop' : '{launchScriptProperty}' - } -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle deleted file mode 100644 index 71e71705fef..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version}' -} - -bootJar { - mainClass = 'com.example.Application' - {launchScript} -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle deleted file mode 100644 index 71e71705fef..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version}' -} - -bootJar { - mainClass = 'com.example.Application' - {launchScript} -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle deleted file mode 100644 index ce8eebfd4ee..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'java' - id 'org.springframework.boot' version '{version}' -} - -bootJar { - mainClass = 'com.example.Application' - launchScript() -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle deleted file mode 100644 index 68d440654f0..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptPropertyChanges.gradle +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'war' - id 'org.springframework.boot' version '{version}' -} - -bootWar { - mainClass = 'com.example.Application' - launchScript { - properties 'prop' : '{launchScriptProperty}' - } -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle deleted file mode 100644 index 3f31269a132..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasIncludedAndThenIsNotIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'war' - id 'org.springframework.boot' version '{version}' -} - -bootWar { - mainClass = 'com.example.Application' - {launchScript} -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle deleted file mode 100644 index 3f31269a132..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-notUpToDateWhenLaunchScriptWasNotIncludedAndThenIsIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'war' - id 'org.springframework.boot' version '{version}' -} - -bootWar { - mainClass = 'com.example.Application' - {launchScript} -} diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle deleted file mode 100644 index 596bf683a9e..00000000000 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-upToDateWhenBuiltTwiceWithLaunchScriptIncluded.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id 'war' - id 'org.springframework.boot' version '{version}' -} - -bootWar { - mainClass = 'com.example.Application' - launchScript() -} diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java b/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java index 10407aaeb5c..94ae84a940c 100644 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java @@ -160,15 +160,6 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests { }); } - @TestTemplate - void whenACustomLaunchScriptIsConfiguredItAppearsInTheRepackagedJar(MavenBuild mavenBuild) { - mavenBuild.project("jar-custom-launcher").goals("install").execute((project) -> { - File repackaged = new File(project, "target/jar-0.0.1.BUILD-SNAPSHOT.jar"); - assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/"); - assertThat(launchScript(repackaged)).contains("Hello world"); - }); - } - @TestTemplate void whenAnEntryIsExcludedItDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) { mavenBuild.project("jar-exclude-entry").goals("install").execute((project) -> { @@ -267,17 +258,6 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests { }); } - @TestTemplate - void whenAJarIsExecutableItBeginsWithTheDefaultLaunchScript(MavenBuild mavenBuild) { - mavenBuild.project("jar-executable").execute((project) -> { - File repackaged = new File(project, "target/jar-executable-0.0.1.BUILD-SNAPSHOT.jar"); - assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/"); - assertThat(launchScript(repackaged)).contains("Spring Boot Startup Script") - .contains("MyFullyExecutableJarName") - .contains("MyFullyExecutableJarDesc"); - }); - } - @TestTemplate void whenAJarIsBuiltWithLibrariesWithConflictingNamesTheyAreMadeUniqueUsingTheirGroupIds(MavenBuild mavenBuild) { mavenBuild.project("jar-lib-name-conflict").execute((project) -> { diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/pom.xml b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/pom.xml deleted file mode 100644 index 6e78c3ea63a..00000000000 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - org.springframework.boot.maven.it - jar - 0.0.1.BUILD-SNAPSHOT - - UTF-8 - @java.version@ - @java.version@ - - - - - @project.groupId@ - @project.artifactId@ - @project.version@ - - - - repackage - - - ${basedir}/src/launcher/custom.script - - world - - - - - - - - diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/launcher/custom.script b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/launcher/custom.script deleted file mode 100644 index f8663275c8a..00000000000 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/launcher/custom.script +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo "Hello {{name}}" diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/main/java/org/test/SampleApplication.java b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/main/java/org/test/SampleApplication.java deleted file mode 100644 index 547d0cf0171..00000000000 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-custom-launcher/src/main/java/org/test/SampleApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.test; - -public class SampleApplication { - - public static void main(String[] args) { - } - -} diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/pom.xml b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/pom.xml deleted file mode 100644 index 802d166a273..00000000000 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - org.springframework.boot.maven.it - jar-executable - MyFullyExecutableJarName - MyFullyExecutableJarDesc - 0.0.1.BUILD-SNAPSHOT - - UTF-8 - @java.version@ - @java.version@ - - - - - @project.groupId@ - @project.artifactId@ - @project.version@ - - - - repackage - - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - @maven-jar-plugin.version@ - - - - some.random.Main - - - - - - - diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/src/main/java/org/test/SampleApplication.java b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/src/main/java/org/test/SampleApplication.java deleted file mode 100644 index 547d0cf0171..00000000000 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/jar-executable/src/main/java/org/test/SampleApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.test; - -public class SampleApplication { - - public static void main(String[] args) { - } - -} diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java index 2ccad7b25f1..781fd69b11e 100644 --- a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java +++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java @@ -20,7 +20,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.attribute.FileTime; import java.util.List; -import java.util.Properties; import java.util.regex.Pattern; import javax.inject.Inject; @@ -36,13 +35,10 @@ import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProjectHelper; import org.jspecify.annotations.Nullable; -import org.springframework.boot.loader.tools.DefaultLaunchScript; -import org.springframework.boot.loader.tools.LaunchScript; import org.springframework.boot.loader.tools.LayoutFactory; import org.springframework.boot.loader.tools.Libraries; import org.springframework.boot.loader.tools.Repackager; import org.springframework.lang.Contract; -import org.springframework.util.StringUtils; /** * Repackage existing JAR and WAR archives so that they can be executed from the command @@ -122,35 +118,6 @@ public class RepackageMojo extends AbstractPackagerMojo { @Parameter private @Nullable List requiresUnpack; - /** - * Make a fully executable jar for *nix machines by prepending a launch script to the - * jar. - *

- * Currently, some tools do not accept this format so you may not always be able to - * use this technique. For example, {@code jar -xf} may silently fail to extract a jar - * or war that has been made fully-executable. It is recommended that you only enable - * this option if you intend to execute it directly, rather than running it with - * {@code java -jar} or deploying it to a servlet container. - * @since 1.3.0 - */ - @Parameter(defaultValue = "false") - private boolean executable; - - /** - * The embedded launch script to prepend to the front of the jar if it is fully - * executable. If not specified the 'Spring Boot' default script will be used. - * @since 1.3.0 - */ - @Parameter - private @Nullable File embeddedLaunchScript; - - /** - * Properties that should be expanded in the embedded launch script. - * @since 1.3.0 - */ - @Parameter - private @Nullable Properties embeddedLaunchScriptProperties; - /** * Timestamp for reproducible output archive entries, either formatted as ISO 8601 * (yyyy-MM-dd'T'HH:mm:ssXXX) or an {@code int} representing seconds @@ -227,8 +194,7 @@ public class RepackageMojo extends AbstractPackagerMojo { Repackager repackager = getRepackager(source.getFile()); Libraries libraries = getLibraries(this.requiresUnpack); try { - LaunchScript launchScript = getLaunchScript(); - repackager.repackage(target, libraries, launchScript, parseOutputTimestamp()); + repackager.repackage(target, libraries, parseOutputTimestamp()); } catch (IOException ex) { throw new MojoExecutionException(ex.getMessage(), ex); @@ -249,41 +215,11 @@ public class RepackageMojo extends AbstractPackagerMojo { return getConfiguredPackager(() -> new Repackager(source)); } - private @Nullable LaunchScript getLaunchScript() throws IOException { - if (this.executable || this.embeddedLaunchScript != null) { - return new DefaultLaunchScript(this.embeddedLaunchScript, buildLaunchScriptProperties()); - } - return null; - } - - private Properties buildLaunchScriptProperties() { - Properties properties = new Properties(); - if (this.embeddedLaunchScriptProperties != null) { - properties.putAll(this.embeddedLaunchScriptProperties); - } - putIfMissing(properties, "initInfoProvides", this.project.getArtifactId()); - putIfMissing(properties, "initInfoShortDescription", this.project.getName(), this.project.getArtifactId()); - putIfMissing(properties, "initInfoDescription", removeLineBreaks(this.project.getDescription()), - this.project.getName(), this.project.getArtifactId()); - return properties; - } - @Contract("!null -> !null") private @Nullable String removeLineBreaks(@Nullable String description) { return (description != null) ? WHITE_SPACE_PATTERN.matcher(description).replaceAll(" ") : null; } - private void putIfMissing(Properties properties, String key, String... valueCandidates) { - if (!properties.containsKey(key)) { - for (String candidate : valueCandidates) { - if (StringUtils.hasLength(candidate)) { - properties.put(key, candidate); - return; - } - } - } - } - private void updateArtifact(Artifact source, File target, File original) { if (this.attach) { attachArtifact(source, target, original); diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/ROOT/pages/redirect.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/ROOT/pages/redirect.adoc index 9e1e5c724e8..b87b5092c28 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/ROOT/pages/redirect.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/ROOT/pages/redirect.adoc @@ -335,7 +335,6 @@ * xref:gradle-plugin:packaging-oci-image.adoc#build-image[gradle-plugin#build-image] * xref:gradle-plugin:packaging.adoc#packaging-executable.and-plain-archives[gradle-plugin#packaging-executable.and-plain-archives] * xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.including-development-only-dependencies[gradle-plugin#packaging-executable.configuring.including-development-only-dependencies] -* xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.launch-script[gradle-plugin#packaging-executable.configuring.launch-script] * xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.layered-archives.configuration[gradle-plugin#packaging-executable.configuring.layered-archives.configuration] * xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.layered-archives[gradle-plugin#packaging-executable.configuring.layered-archives] * xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.main-class[gradle-plugin#packaging-executable.configuring.main-class] @@ -502,23 +501,6 @@ * xref:how-to:deployment/index.adoc#howto.deployment[#deployment] * xref:how-to:deployment/index.adoc[#deployment] * xref:how-to:deployment/index.adoc[deployment] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running.conf-file[#deployment.installing.init-d.script-customization.when-running.conf-file] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running.conf-file[#deployment.installing.nix-services.script-customization.when-running.conf-file] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running[#deployment-script-customization-when-it-runs] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running[#deployment.installing.init-d.script-customization.when-running] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running[#deployment.installing.nix-services.script-customization.when-running] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-written[#deployment-script-customization-when-it-written] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-written[#deployment.installing.init-d.script-customization.when-written] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-written[#deployment.installing.nix-services.script-customization.when-written] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization[#deployment-script-customization] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization[#deployment.installing.init-d.script-customization] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization[#deployment.installing.nix-services.script-customization] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.securing[#deployment-initd-service-securing] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.securing[#deployment.installing.init-d.securing] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d.securing[#deployment.installing.nix-services.init-d.securing] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d[#deployment-initd-service] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d[#deployment.installing.init-d] -* xref:how-to:deployment/installing.adoc#howto.deployment.installing.init-d[#deployment.installing.nix-services.init-d] * xref:how-to:deployment/installing.adoc#howto.deployment.installing.system-d[#deployment-systemd-service] * xref:how-to:deployment/installing.adoc#howto.deployment.installing.system-d[#deployment.installing.nix-services.system-d] * xref:how-to:deployment/installing.adoc#howto.deployment.installing.system-d[#deployment.installing.system-d] @@ -879,13 +861,10 @@ * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.optional-parameters[maven-plugin#packaging.repackage-goal.optional-parameters] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.attach[maven-plugin#packaging.repackage-goal.parameter-details.attach] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.classifier[maven-plugin#packaging.repackage-goal.parameter-details.classifier] -* xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.embedded-launch-script-properties[maven-plugin#packaging.repackage-goal.parameter-details.embedded-launch-script-properties] -* xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.embedded-launch-script[maven-plugin#packaging.repackage-goal.parameter-details.embedded-launch-script] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.exclude-devtools[maven-plugin#packaging.repackage-goal.parameter-details.exclude-devtools] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.exclude-docker-compose[maven-plugin#packaging.repackage-goal.parameter-details.exclude-docker-compose] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.exclude-group-ids[maven-plugin#packaging.repackage-goal.parameter-details.exclude-group-ids] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.excludes[maven-plugin#packaging.repackage-goal.parameter-details.excludes] -* xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.executable[maven-plugin#packaging.repackage-goal.parameter-details.executable] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.include-system-scope[maven-plugin#packaging.repackage-goal.parameter-details.include-system-scope] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.include-tools[maven-plugin#packaging.repackage-goal.parameter-details.include-tools] * xref:maven-plugin:packaging.adoc#packaging.repackage-goal.parameter-details.includes[maven-plugin#packaging.repackage-goal.parameter-details.includes] diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/index.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/index.adoc index cb8b88a7b6e..4530bc829b8 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/index.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/index.adoc @@ -2,7 +2,7 @@ = Deploying Spring Boot Applications Spring Boot's flexible packaging options provide a great deal of choice when it comes to deploying your application. -You can deploy Spring Boot applications to a variety of cloud platforms, to virtual/real machines, or make them fully executable for Unix systems. +You can deploy Spring Boot applications to a variety of cloud platforms and to virtual or real machines. This section covers some of the more common deployment scenarios. diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/installing.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/installing.adoc index 303db28c9a7..4cb535c54de 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/installing.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/deployment/installing.adoc @@ -1,7 +1,7 @@ [[howto.deployment.installing]] = Installing Spring Boot Applications -In addition to running Spring Boot applications by using `java -jar` directly, it is also possible to run them as `systemd`, `init.d` or Windows services. +In addition to running Spring Boot applications by using `java -jar` directly, it is also possible to run them as services. @@ -51,335 +51,6 @@ Run `man systemctl` for more details. -[[howto.deployment.installing.init-d]] -== Installation as an init.d Service (System V) - -To use your application as `init.d` service, configure its build to produce a xref:deployment/installing.adoc[fully executable jar]. - -CAUTION: Fully executable jars work by embedding an extra script at the front of the file. -Currently, some tools do not accept this format, so you may not always be able to use this technique. -For example, `jar -xf` may silently fail to extract a jar or war that has been made fully executable. -It is recommended that you make your jar or war fully executable only if you intend to execute it directly, rather than running it with `java -jar` or deploying it to a servlet container. - -CAUTION: A zip64-format jar file cannot be made fully executable. -Attempting to do so will result in a jar file that is reported as corrupt when executed directly or with `java -jar`. -A standard-format jar file that contains one or more zip64-format nested jars can be fully executable. - -To create a '`fully executable`' jar with Maven, use the following plugin configuration: - -[source,xml] ----- - - org.springframework.boot - spring-boot-maven-plugin - - true - - ----- - -The following example shows the equivalent Gradle configuration: - -[source,gradle] ----- -tasks.named('bootJar') { - launchScript() -} ----- - -It can then be symlinked to `init.d` to support the standard `start`, `stop`, `restart`, and `status` commands. - -The default launch script that is added to a fully executable jar supports most Linux distributions and is tested on CentOS and Ubuntu. -Other platforms, such as OS X and FreeBSD, require the use of a custom script. -The default scripts supports the following features: - -* Starts the services as the user that owns the jar file -* Tracks the application's PID by using `/var/run//.pid` -* Writes console logs to `/var/log/.log` - -Assuming that you have a Spring Boot application installed in `/var/myapp`, to install a Spring Boot application as an `init.d` service, create a symlink, as follows: - -[source,shell] ----- -$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp ----- - -Once installed, you can start and stop the service in the usual way. -For example, on a Debian-based system, you could start it with the following command: - -[source,shell] ----- -$ service myapp start ----- - -TIP: If your application fails to start, check the log file written to `/var/log/.log` for errors. - -You can also flag the application to start automatically by using your standard operating system tools. -For example, on Debian, you could use the following command: - -[source,shell] ----- -$ update-rc.d myapp defaults ----- - - - -[[howto.deployment.installing.init-d.securing]] -=== Securing an init.d Service - -NOTE: The following is a set of guidelines on how to secure a Spring Boot application that runs as an init.d service. -It is not intended to be an exhaustive list of everything that should be done to harden an application and the environment in which it runs. - -When executed as root, as is the case when root is being used to start an init.d service, the default executable script runs the application as the user specified in the `RUN_AS_USER` environment variable. -When the environment variable is not set, the user who owns the jar file is used instead. -You should never run a Spring Boot application as `root`, so `RUN_AS_USER` should never be root and your application's jar file should never be owned by root. -Instead, create a specific user to run your application and set the `RUN_AS_USER` environment variable or use `chown` to make it the owner of the jar file, as shown in the following example: - -[source,shell] ----- -$ chown bootapp:bootapp your-app.jar ----- - -In this case, the default executable script runs the application as the `bootapp` user. - -TIP: To reduce the chances of the application's user account being compromised, you should consider preventing it from using a login shell. -For example, you can set the account's shell to `/usr/sbin/nologin`. - -You should also take steps to prevent the modification of your application's jar file. -Firstly, configure its permissions so that it cannot be written and can only be read or executed by its owner, as shown in the following example: - -[source,shell] ----- -$ chmod 500 your-app.jar ----- - -Second, you should also take steps to limit the damage if your application or the account that is running it is compromised. -If an attacker does gain access, they could make the jar file writable and change its contents. -One way to protect against this is to make it immutable by using `chattr`, as shown in the following example: - -[source,shell] ----- -$ sudo chattr +i your-app.jar ----- - -This will prevent any user, including root, from modifying the jar. - -If root is used to control the application's service and you xref:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running.conf-file[use a `.conf` file] to customize its startup, the `.conf` file is read and evaluated by the root user. -It should be secured accordingly. -Use `chmod` so that the file can only be read by the owner and use `chown` to make root the owner, as shown in the following example: - -[source,shell] ----- -$ chmod 400 your-app.conf -$ sudo chown root:root your-app.conf ----- - - - -[[howto.deployment.installing.init-d.script-customization]] -=== Customizing the Startup Script - -The default embedded startup script written by the Maven or Gradle plugin can be customized in a number of ways. -For most people, using the default script along with a few customizations is usually enough. -If you find you cannot customize something that you need to, use the `embeddedLaunchScript` option to write your own file entirely. - - - -[[howto.deployment.installing.init-d.script-customization.when-written]] -==== Customizing the Start Script When It Is Written - -It often makes sense to customize elements of the start script as it is written into the jar file. -For example, init.d scripts can provide a "`description`". -Since you know the description up front (and it need not change), you may as well provide it when the jar is generated. - -To customize written elements, use the `embeddedLaunchScriptProperties` option of the Spring Boot Maven plugin or the xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.launch-script[`properties` property of the Spring Boot Gradle plugin's `launchScript`]. - -The following property substitutions are supported with the default script: - -[cols="1,3,3,3"] -|=== -| Name | Description | Gradle default | Maven default - -| `mode` -| The script mode. -| `auto` -| `auto` - -| `initInfoProvides` -| The `Provides` section of "`INIT INFO`" -| `${task.baseName}` -| `${project.artifactId}` - -| `initInfoRequiredStart` -| `Required-Start` section of "`INIT INFO`". -| `$remote_fs $syslog $network` -| `$remote_fs $syslog $network` - -| `initInfoRequiredStop` -| `Required-Stop` section of "`INIT INFO`". -| `$remote_fs $syslog $network` -| `$remote_fs $syslog $network` - -| `initInfoDefaultStart` -| `Default-Start` section of "`INIT INFO`". -| `2 3 4 5` -| `2 3 4 5` - -| `initInfoDefaultStop` -| `Default-Stop` section of "`INIT INFO`". -| `0 1 6` -| `0 1 6` - -| `initInfoShortDescription` -| `Short-Description` section of "`INIT INFO`". -| Single-line version of `${project.description}` (falling back to `${task.baseName}`) -| `${project.name}` - -| `initInfoDescription` -| `Description` section of "`INIT INFO`". -| `${project.description}` (falling back to `${task.baseName}`) -| `${project.description}` (falling back to `${project.name}`) - -| `initInfoChkconfig` -| `chkconfig` section of "`INIT INFO`" -| `2345 99 01` -| `2345 99 01` - -| `confFolder` -| The default value for `CONF_FOLDER` -| Folder containing the jar -| Folder containing the jar - -| `inlinedConfScript` -| Reference to a file script that should be inlined in the default launch script. - This can be used to set environmental variables such as `JAVA_OPTS` before any external config files are loaded -| -| - -| `logFolder` -| Default value for `LOG_FOLDER`. - Only valid for an `init.d` service -| -| - -| `logFilename` -| Default value for `LOG_FILENAME`. - Only valid for an `init.d` service -| -| - -| `pidFolder` -| Default value for `PID_FOLDER`. - Only valid for an `init.d` service -| -| - -| `pidFilename` -| Default value for the name of the PID file in `PID_FOLDER`. - Only valid for an `init.d` service -| -| - -| `useStartStopDaemon` -| Whether the `start-stop-daemon` command, when it is available, should be used to control the process -| `true` -| `true` - -| `stopWaitTime` -| Default value for `STOP_WAIT_TIME` in seconds. - Only valid for an `init.d` service -| 60 -| 60 -|=== - - - -[[howto.deployment.installing.init-d.script-customization.when-running]] -==== Customizing a Script When It Runs - -For items of the script that need to be customized _after_ the jar has been written, you can use environment variables or a xref:deployment/installing.adoc#howto.deployment.installing.init-d.script-customization.when-running.conf-file[config file]. - -The following environment properties are supported with the default script: - -[cols="1,6"] -|=== -| Variable | Description - -| `MODE` -| The "`mode`" of operation. - The default depends on the way the jar was built but is usually `auto` (meaning it tries to guess if it is an init script by checking if it is a symlink in a directory called `init.d`). - You can explicitly set it to `service` so that the `stop\|start\|status\|restart` commands work or to `run` if you want to run the script in the foreground. - -| `RUN_AS_USER` -| The user that will be used to run the application. - When not set, the user that owns the jar file will be used. - -| `USE_START_STOP_DAEMON` -| Whether the `start-stop-daemon` command, when it is available, should be used to control the process. - Defaults to `true`. - -| `PID_FOLDER` -| The root name of the pid folder (`/var/run` by default). - -| `LOG_FOLDER` -| The name of the folder in which to put log files (`/var/log` by default). - -| `CONF_FOLDER` -| The name of the folder from which to read .conf files (same folder as jar-file by default). - -| `LOG_FILENAME` -| The name of the log file in the `LOG_FOLDER` (`.log` by default). - -| `APP_NAME` -| The name of the app. - If the jar is run from a symlink, the script guesses the app name. - If it is not a symlink or you want to explicitly set the app name, this can be useful. - -| `RUN_ARGS` -| The arguments to pass to the program (the Spring Boot app). - -| `JAVA_HOME` -| The location of the `java` executable is discovered by using the `PATH` by default, but you can set it explicitly if there is an executable file at `$JAVA_HOME/bin/java`. - -| `JAVA_OPTS` -| Options that are passed to the JVM when it is launched. - -| `JARFILE` -| The explicit location of the jar file, in case the script is being used to launch a jar that it is not actually embedded. - -| `DEBUG` -| If not empty, sets the `-x` flag on the shell process, allowing you to see the logic in the script. - -| `STOP_WAIT_TIME` -| The time in seconds to wait when stopping the application before forcing a shutdown (`60` by default). -|=== - -NOTE: The `PID_FOLDER`, `LOG_FOLDER`, and `LOG_FILENAME` variables are only valid for an `init.d` service. -For `systemd`, the equivalent customizations are made by using the '`service`' script. -See the https://www.freedesktop.org/software/systemd/man/systemd.service.html[service unit configuration man page] for more details. - - - -[[howto.deployment.installing.init-d.script-customization.when-running.conf-file]] -===== Using a Conf File - -With the exception of `JARFILE` and `APP_NAME`, the settings listed in the preceding section can be configured by using a `.conf` file. -The file is expected to be next to the jar file and have the same name but suffixed with `.conf` rather than `.jar`. -For example, a jar named `/var/myapp/myapp.jar` uses the configuration file named `/var/myapp/myapp.conf`, as shown in the following example: - -.myapp.conf -[source,properties] ----- -JAVA_OPTS=-Xmx1024M -LOG_FOLDER=/custom/log/folder ----- - -TIP: If you do not like having the config file next to the jar file, you can set a `CONF_FOLDER` environment variable to customize the location of the config file. - -To learn about securing this file appropriately, see xref:deployment/installing.adoc#howto.deployment.installing.init-d.securing[the guidelines for securing an init.d service]. - - - [[howto.deployment.installing.windows-services]] == Microsoft Windows Services diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc index 0e43466a171..935998556fc 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc @@ -5,9 +5,6 @@ While it is possible to convert a Spring Boot uber jar into a Docker image with When you create a jar containing the layers index file, the `spring-boot-jarmode-tools` jar will be added as a dependency to your jar. With this jar on the classpath, you can launch your application in a special mode which allows the bootstrap code to run something entirely different from your application, for example, something that extracts the layers. -CAUTION: The `tools` mode can not be used with a xref:how-to:deployment/installing.adoc[fully executable Spring Boot archive] that includes a launch script. -Disable launch script configuration when building a jar file that is intended to be used with the `extract` tools mode command. - Here’s how you can launch your jar with a `tools` jar mode: [source,shell] diff --git a/integration-test/spring-boot-launch-script-integration-tests/README.adoc b/integration-test/spring-boot-launch-script-integration-tests/README.adoc deleted file mode 100644 index d4eba967c06..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/README.adoc +++ /dev/null @@ -1,61 +0,0 @@ -= Spring Boot Launch Script Tests - -This module contains integration tests for the default launch script that is used -to make a jar file fully executable on Linux. The tests use Docker to verify the -functionality in a variety of Linux distributions. - - - -== Setting up Docker - -The setup that's required varies depending on your operating system. - - - -=== Docker on OS X - -Install Docker for Mac. See the https://docs.docker.com/docker-for-mac/install/[macOS -installation instructions] for details. - - - -=== Docker on Linux - -Install Docker as appropriate for your Linux distribution. See the -https://docs.docker.com/engine/installation/[Linux installation instructions] for more -information. - -Next, add your user to the `docker` group. For example: - ----- -$ sudo usermod -a -G docker awilkinson ----- - -You may need to log out and back in again for this change to take effect and for your -user to be able to connect to the daemon. - - - -== Running the tests - -You're now ready to run the tests. Assuming that you're in the same directory as this -README, the tests can be launched as follows: - ----- -$ gradle intTest ----- - -The first time the tests are run, Docker will create the container images that are used to -run the tests. This can take several minutes, particularly if you have a slow network -connection. Subsequent runs will be faster as the images are cached locally. You can run -`docker images` to see a list of the cached images. Images created by these tests will be -tagged with `spring-boot-it` prefix to easily distinguish them. - - - -== Cleaning up - -If you want to reclaim the disk space used by the cached images (at the expense of having -to wait for them to be downloaded and rebuilt the next time you run the tests), you can -use `docker images` to list the images and `docker rmi ` to delete them (look for -`spring-boot-it` tag). See `docker rmi --help` for further details. diff --git a/integration-test/spring-boot-launch-script-integration-tests/build.gradle b/integration-test/spring-boot-launch-script-integration-tests/build.gradle deleted file mode 100644 index f86cb329e4e..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id "java" - id "org.springframework.boot.docker-test" - id "de.undercouch.download" -} - -description = "Spring Boot Launch Script Integration Tests" - -def jdkVersion = "17.0.11+10" -def jdkArch = "aarch64".equalsIgnoreCase(System.getProperty("os.arch")) ? "aarch64" : "amd64" - -configurations { - app -} - -dependencies { - app project(path: ":platform:spring-boot-dependencies", configuration: "mavenRepository") - app project(path: ":build-plugin:spring-boot-gradle-plugin", configuration: "mavenRepository") - - dockerTestImplementation(project(":test-support:spring-boot-docker-test-support")) - dockerTestImplementation(project(":starter:spring-boot-starter-test")) - dockerTestImplementation("org.testcontainers:testcontainers") -} - -tasks.register("syncMavenRepository", Sync) { - from configurations.app - into layout.buildDirectory.dir("docker-test-maven-repository") -} - -tasks.register("syncAppSource", org.springframework.boot.build.SyncAppSource) { - sourceDirectory = file("spring-boot-launch-script-tests-app") - destinationDirectory = file(layout.buildDirectory.dir("spring-boot-launch-script-tests-app")) -} - -tasks.register("buildApp", GradleBuild) { - dependsOn syncAppSource, syncMavenRepository - dir = layout.buildDirectory.dir("spring-boot-launch-script-tests-app") - startParameter.buildCacheEnabled = false - tasks = ["build"] -} - -tasks.register("downloadJdk", Download) { - def destFolder = new File(project.gradle.gradleUserHomeDir, "caches/springboot/downloads/jdk/bellsoft") - destFolder.mkdirs() - src "https://download.bell-sw.com/java/${jdkVersion}/bellsoft-jdk${jdkVersion}-linux-${jdkArch}.tar.gz" - dest destFolder - tempAndMove true - overwrite false - retries 3 -} - -tasks.register("syncJdkDownloads", Sync) { - dependsOn downloadJdk - from "${project.gradle.gradleUserHomeDir}/caches/springboot/downloads/jdk/bellsoft/" - include "bellsoft-jdk${jdkVersion}-linux-${jdkArch}.tar.gz" - into layout.buildDirectory.dir("downloads/jdk/bellsoft/") -} - -tasks.named("processDockerTestResources").configure { - dependsOn syncJdkDownloads -} - -tasks.named("dockerTest").configure { - dependsOn buildApp -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/build.gradle b/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/build.gradle deleted file mode 100644 index 1f39d3f484d..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -plugins { - id "java" - id "org.springframework.boot" -} - -java { - sourceCompatibility = '17' - targetCompatibility = '17' -} - -repositories { - maven { url = layout.projectDirectory.dir("../docker-test-maven-repository") } - mavenCentral() - spring.mavenRepositories() -} - -dependencies { - implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) - implementation("org.apache.tomcat.embed:tomcat-embed-core") -} - -bootJar { - launchScript() -} \ No newline at end of file diff --git a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/settings.gradle b/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/settings.gradle deleted file mode 100644 index fa84f001ab3..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/settings.gradle +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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. - */ - -pluginManagement { - evaluate(new File("${gradle.parent.rootProject.rootDir}/buildSrc/SpringRepositorySupport.groovy")).apply(this) - repositories { - maven { url = layout.settingsDirectory.dir("../docker-test-maven-repository") } - mavenCentral() - spring.mavenRepositories() - } - resolutionStrategy { - eachPlugin { - if (requested.id.id == "org.springframework.boot") { - useModule "org.springframework.boot:spring-boot-gradle-plugin:${requested.version}" - } - } - } -} \ No newline at end of file diff --git a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/src/main/java/org/springframework/boot/launchscript/LaunchScriptTestApplication.java b/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/src/main/java/org/springframework/boot/launchscript/LaunchScriptTestApplication.java deleted file mode 100644 index 58575404868..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/spring-boot-launch-script-tests-app/src/main/java/org/springframework/boot/launchscript/LaunchScriptTestApplication.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.launchscript; - -import java.io.IOException; -import java.net.URL; -import java.security.CodeSource; -import java.security.ProtectionDomain; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import org.apache.catalina.Context; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.startup.Tomcat; - -public class LaunchScriptTestApplication { - - public static void main(String[] args) throws LifecycleException { - System.out.println("Starting " + LaunchScriptTestApplication.class.getSimpleName() + " (" + findSource() + ")"); - Tomcat tomcat = new Tomcat(); - tomcat.getConnector().setPort(getPort(args)); - Context context = tomcat.addContext(getContextPath(args), null); - tomcat.addServlet(context.getPath(), "test", new HttpServlet() { - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - resp.getWriter().println("Launched"); - } - - }); - context.addServletMappingDecoded("/", "test"); - tomcat.start(); - } - - private static URL findSource() { - try { - ProtectionDomain domain = LaunchScriptTestApplication.class.getProtectionDomain(); - CodeSource codeSource = (domain != null) ? domain.getCodeSource() : null; - return (codeSource != null) ? codeSource.getLocation() : null; - } - catch (Exception ex) { - } - return null; - } - - private static int getPort(String[] args) { - String port = getProperty(args, "server.port"); - return (port != null) ? Integer.parseInt(port) : 8080; - } - - private static String getContextPath(String[] args) { - String contextPath = getProperty(args, "server.servlet.context-path"); - return (contextPath != null) ? contextPath : ""; - } - - private static String getProperty(String[] args, String property) { - String value = System.getProperty(property); - if (value != null) { - return value; - } - String prefix = "--" + property + "="; - for (String arg : args) { - if (arg.startsWith(prefix)) { - return arg.substring(prefix.length()); - } - } - return null; - } - -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/AbstractLaunchScriptIntegrationTests.java b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/AbstractLaunchScriptIntegrationTests.java deleted file mode 100644 index 06aa49d6a42..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/AbstractLaunchScriptIntegrationTests.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.launchscript; - -import java.io.File; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.function.Predicate; - -import org.assertj.core.api.Condition; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.output.Slf4jLogConsumer; -import org.testcontainers.containers.output.ToStringConsumer; -import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.utility.MountableFile; - -import org.springframework.boot.ansi.AnsiColor; -import org.springframework.util.Assert; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.containsString; - -/** - * Abstract base class for testing the launch script. - * - * @author Andy Wilkinson - * @author Ali Shahbour - * @author Alexey Vinogradov - * @author Moritz Halbritter - */ -abstract class AbstractLaunchScriptIntegrationTests { - - protected static final char ESC = 27; - - private final String scriptsDir; - - protected AbstractLaunchScriptIntegrationTests(String scriptsDir) { - this.scriptsDir = scriptsDir; - } - - static List filterParameters(Predicate osFilter) { - List parameters = new ArrayList<>(); - for (File os : new File("src/dockerTest/resources/conf").listFiles()) { - if (osFilter.test(os)) { - for (File version : os.listFiles()) { - parameters.add(new Object[] { os.getName(), version.getName() }); - } - } - } - return parameters; - } - - protected Condition coloredString(AnsiColor color, String string) { - String colorString = ESC + "[0;" + color + "m" + string + ESC + "[0m"; - return new Condition<>() { - - @Override - public boolean matches(String value) { - return containsString(colorString).matches(value); - } - - }; - } - - protected void doLaunch(String os, String version, String script) throws Exception { - assertThat(doTest(os, version, script)).contains("Launched"); - } - - protected String doTest(String os, String version, String script) throws Exception { - ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - try (LaunchScriptTestContainer container = new LaunchScriptTestContainer(os, version, this.scriptsDir, - script)) { - container.withLogConsumer(consumer); - container.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger("docker"))); - container.start(); - while (container.isRunning()) { - Thread.sleep(100); - } - } - return consumer.toUtf8String(); - } - - private static final class LaunchScriptTestContainer extends GenericContainer { - - private LaunchScriptTestContainer(String os, String version, String scriptsDir, String testScript) { - super(createImage(os, version)); - withCopyFileToContainer(MountableFile.forHostPath(findApplication().getAbsolutePath()), "/app.jar"); - withCopyFileToContainer( - MountableFile.forHostPath("src/dockerTest/resources/scripts/" + scriptsDir + "test-functions.sh"), - "/test-functions.sh"); - withCopyFileToContainer( - MountableFile.forHostPath("src/dockerTest/resources/scripts/" + scriptsDir + testScript), - "/" + testScript); - withCommand("/bin/bash", "-c", - "chown root:root *.sh && chown root:root *.jar && chmod +x " + testScript + " && ./" + testScript); - withStartupCheckStrategy(new OneShotStartupCheckStrategy().withTimeout(Duration.ofMinutes(5))); - } - - private static ImageFromDockerfile createImage(String os, String version) { - ImageFromDockerfile image = new ImageFromDockerfile( - "spring-boot-launch-script/" + os.toLowerCase(Locale.ROOT) + "-" + version); - image.withFileFromFile("Dockerfile", - new File("src/dockerTest/resources/conf/" + os + "/" + version + "/Dockerfile")); - for (File file : new File("build/downloads/jdk/bellsoft").listFiles()) { - image.withFileFromFile("downloads/" + file.getName(), file); - } - return image; - } - - private static File findApplication() { - String name = String.format("build/%1$s/build/libs/%1$s.jar", "spring-boot-launch-script-tests-app"); - File jar = new File(name); - Assert.state(jar.isFile(), () -> "Could not find " + name + ". Have you built it?"); - return jar; - } - - } - -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/JarLaunchScriptIntegrationTests.java b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/JarLaunchScriptIntegrationTests.java deleted file mode 100644 index d8b0195ac1e..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/JarLaunchScriptIntegrationTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.launchscript; - -import java.util.List; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Integration tests of Spring Boot's launch script when executing the jar directly. - * - * @author Alexey Vinogradov - * @author Andy Wilkinson - */ -@DisabledIfDockerUnavailable -class JarLaunchScriptIntegrationTests extends AbstractLaunchScriptIntegrationTests { - - JarLaunchScriptIntegrationTests() { - super("jar/"); - } - - static List parameters() { - return filterParameters((file) -> true); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void basicLaunch(String os, String version) throws Exception { - doLaunch(os, version, "basic-launch.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithDebugEnv(String os, String version) throws Exception { - final String output = doTest(os, version, "launch-with-debug.sh"); - assertThat(output).contains("++ pwd"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithDifferentJarFileEnv(String os, String version) throws Exception { - final String output = doTest(os, version, "launch-with-jarfile.sh"); - assertThat(output).contains("app-another.jar"); - assertThat(output).doesNotContain("spring-boot-launch-script-tests.jar"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleCommandLineArgument(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-command-line-argument.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleCommandLineArguments(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-command-line-arguments.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleRunArg(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-run-arg.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleRunArgs(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-run-args.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleJavaOpt(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-java-opt.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleJavaOpts(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-java-opts.sh"); - } - -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIntegrationTests.java b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIntegrationTests.java deleted file mode 100644 index 2622f196052..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIntegrationTests.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.launchscript; - -import java.util.List; -import java.util.regex.Pattern; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import org.springframework.boot.ansi.AnsiColor; -import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Integration tests for Spring Boot's launch script on OSs that use SysVinit. - * - * @author Andy Wilkinson - * @author Ali Shahbour - * @author Alexey Vinogradov - * @author Moritz Halbritter - */ -@DisabledIfDockerUnavailable -class SysVinitLaunchScriptIntegrationTests extends AbstractLaunchScriptIntegrationTests { - - SysVinitLaunchScriptIntegrationTests() { - super("init.d/"); - } - - static List parameters() { - return filterParameters((file) -> !file.getName().contains("RedHat")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void statusWhenStopped(String os, String version) throws Exception { - String output = doTest(os, version, "status-when-stopped.sh"); - assertThat(output).contains("Status: 3"); - assertThat(output).has(coloredString(AnsiColor.RED, "Not running")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void statusWhenStarted(String os, String version) throws Exception { - String output = doTest(os, version, "status-when-started.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extractPid(output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void statusWhenKilled(String os, String version) throws Exception { - String output = doTest(os, version, "status-when-killed.sh"); - assertThat(output).contains("Status: 1"); - assertThat(output) - .has(coloredString(AnsiColor.RED, "Not running (process " + extractPid(output) + " not found)")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void stopWhenStopped(String os, String version) throws Exception { - String output = doTest(os, version, "stop-when-stopped.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.YELLOW, "Not running (pidfile not found)")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void forceStopWhenStopped(String os, String version) throws Exception { - String output = doTest(os, version, "force-stop-when-stopped.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.YELLOW, "Not running (pidfile not found)")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void startWhenStarted(String os, String version) throws Exception { - String output = doTest(os, version, "start-when-started.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.YELLOW, "Already running [" + extractPid(output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void restartWhenStopped(String os, String version) throws Exception { - String output = doTest(os, version, "restart-when-stopped.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.YELLOW, "Not running (pidfile not found)")); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extractPid(output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void restartWhenStarted(String os, String version) throws Exception { - String output = doTest(os, version, "restart-when-started.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extract("PID1", output) + "]")); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Stopped [" + extract("PID1", output) + "]")); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extract("PID2", output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void startWhenStopped(String os, String version) throws Exception { - String output = doTest(os, version, "start-when-stopped.sh"); - assertThat(output).contains("Status: 0"); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extractPid(output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void basicLaunch(String os, String version) throws Exception { - String output = doTest(os, version, "basic-launch.sh"); - assertThat(output).doesNotContain("PID_FOLDER"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMissingLogFolderGeneratesAWarning(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-missing-log-folder.sh"); - assertThat(output) - .has(coloredString(AnsiColor.YELLOW, "LOG_FOLDER /does/not/exist does not exist. Falling back to /tmp")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMissingPidFolderGeneratesAWarning(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-missing-pid-folder.sh"); - assertThat(output) - .has(coloredString(AnsiColor.YELLOW, "PID_FOLDER /does/not/exist does not exist. Falling back to /tmp")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleCommandLineArgument(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-command-line-argument.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleCommandLineArguments(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-command-line-arguments.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleRunArg(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-run-arg.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleRunArgs(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-run-args.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithSingleJavaOpt(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-single-java-opt.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithDoubleLinkSingleJavaOpt(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-double-link-single-java-opt.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithMultipleJavaOpts(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-multiple-java-opts.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithUseOfStartStopDaemonDisabled(String os, String version) throws Exception { - doLaunch(os, version, "launch-with-use-of-start-stop-daemon-disabled.sh"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithRelativePidFolder(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-relative-pid-folder.sh"); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Started [" + extractPid(output) + "]")); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Running [" + extractPid(output) + "]")); - assertThat(output).has(coloredString(AnsiColor.GREEN, "Stopped [" + extractPid(output) + "]")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void pidFolderOwnership(String os, String version) throws Exception { - String output = doTest(os, version, "pid-folder-ownership.sh"); - assertThat(output).contains("phil root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void pidFileOwnership(String os, String version) throws Exception { - String output = doTest(os, version, "pid-file-ownership.sh"); - assertThat(output).contains("phil root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void logFileOwnership(String os, String version) throws Exception { - String output = doTest(os, version, "log-file-ownership.sh"); - assertThat(output).contains("phil root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void logFileOwnershipIsChangedWhenCreated(String os, String version) throws Exception { - String output = doTest(os, version, "log-file-ownership-is-changed-when-created.sh"); - assertThat(output).contains("andy root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void logFileOwnershipIsUnchangedWhenExists(String os, String version) throws Exception { - String output = doTest(os, version, "log-file-ownership-is-unchanged-when-exists.sh"); - assertThat(output).contains("root root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithRelativeLogFolder(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-relative-log-folder.sh"); - assertThat(output).contains("Log written"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void launchWithRunAsUser(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-run-as-user.sh"); - assertThat(output).contains("wagner root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void whenRunAsUserDoesNotExistLaunchFailsWithInvalidArgument(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-run-as-invalid-user.sh"); - assertThat(output).contains("Status: 2"); - assertThat(output).has(coloredString(AnsiColor.RED, "Cannot run as 'johndoe': no such user")); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void whenJarOwnerAndRunAsUserAreBothSpecifiedRunAsUserTakesPrecedence(String os, String version) throws Exception { - String output = doTest(os, version, "launch-with-run-as-user-preferred-to-jar-owner.sh"); - assertThat(output).contains("wagner root"); - } - - @ParameterizedTest(name = "{0} {1}") - @MethodSource("parameters") - void whenLaunchedUsingNonRootUserWithRunAsUserSpecifiedLaunchFailsWithInsufficientPrivilege(String os, - String version) throws Exception { - String output = doTest(os, version, "launch-with-run-as-user-root-required.sh"); - assertThat(output).contains("Status: 4"); - assertThat(output).has(coloredString(AnsiColor.RED, "Cannot run as 'wagner': current user is not root")); - } - - private String extractPid(String output) { - return extract("PID", output); - } - - private String extract(String label, String output) { - Pattern pattern = Pattern.compile(".*" + label + ": ([0-9]+).*", Pattern.DOTALL); - java.util.regex.Matcher matcher = pattern.matcher(output); - if (matcher.matches()) { - return matcher.group(1); - } - throw new IllegalArgumentException("Failed to extract " + label + " from output: " + output); - } - -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/RedHat/ubi9-9.3-1476/Dockerfile b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/RedHat/ubi9-9.3-1476/Dockerfile deleted file mode 100644 index 8d18a1046bb..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/RedHat/ubi9-9.3-1476/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM redhat/ubi9:9.3-1476 as prepare -COPY downloads/* /opt/download/ -RUN mkdir -p /opt/jdk && \ - cd /opt/jdk && \ - tar xzf /opt/download/* --strip-components=1 - -FROM redhat/ubi9:9.3-1476 -COPY --from=prepare /opt/jdk /opt/jdk -ENV JAVA_HOME /opt/jdk -ENV PATH $JAVA_HOME/bin:$PATH diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/jammy/Dockerfile b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/jammy/Dockerfile deleted file mode 100644 index 4419156cd33..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/jammy/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM ubuntu:jammy-20240405 as prepare -COPY downloads/* /opt/download/ -RUN mkdir -p /opt/jdk && \ - cd /opt/jdk && \ - tar xzf /opt/download/* --strip-components=1 - -FROM ubuntu:jammy-20240405 -RUN apt-get update && apt-get install -y software-properties-common curl -COPY --from=prepare /opt/jdk /opt/jdk -ENV JAVA_HOME /opt/jdk -ENV PATH $JAVA_HOME/bin:$PATH diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/noble/Dockerfile b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/noble/Dockerfile deleted file mode 100644 index 8da019058be..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/conf/Ubuntu/noble/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM ubuntu:noble-20250404 as prepare -COPY downloads/* /opt/download/ -RUN mkdir -p /opt/jdk && \ - cd /opt/jdk && \ - tar xzf /opt/download/* --strip-components=1 - -FROM ubuntu:noble-20250404 -RUN apt-get update && apt-get install -y software-properties-common curl -COPY --from=prepare /opt/jdk /opt/jdk -ENV JAVA_HOME /opt/jdk -ENV PATH $JAVA_HOME/bin:$PATH diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/logback.xml b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/logback.xml deleted file mode 100644 index 13e689a2930..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/logback.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/basic-launch.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/basic-launch.sh deleted file mode 100755 index 44f44a856c6..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/basic-launch.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -install_service -start_service -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/force-stop-when-stopped.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/force-stop-when-stopped.sh deleted file mode 100644 index 465b5553296..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/force-stop-when-stopped.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -install_service -force_stop_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-double-link-single-java-opt.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-double-link-single-java-opt.sh deleted file mode 100755 index 6895c0d0613..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-double-link-single-java-opt.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_double_link_service -echo 'JAVA_OPTS=-Dserver.port=8081' > /test-service/spring-boot-app.conf -start_service -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-log-folder.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-log-folder.sh deleted file mode 100755 index 1f3aed38443..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-log-folder.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'LOG_FOLDER=/does/not/exist' > /test-service/spring-boot-app.conf -start_service -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-pid-folder.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-pid-folder.sh deleted file mode 100755 index 83430bea62f..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-missing-pid-folder.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'PID_FOLDER=/does/not/exist' > /test-service/spring-boot-app.conf -start_service -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-command-line-arguments.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-command-line-arguments.sh deleted file mode 100755 index 7503458301f..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-command-line-arguments.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -install_service -start_service --server.port=8081 --server.servlet.context-path=/test -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-java-opts.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-java-opts.sh deleted file mode 100755 index 387ad47dad0..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-java-opts.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'JAVA_OPTS="-Dserver.port=8081 -Dserver.servlet.context-path=/test"' > /test-service/spring-boot-app.conf -start_service -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-run-args.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-run-args.sh deleted file mode 100755 index 76b4c476795..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-multiple-run-args.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'RUN_ARGS="--server.port=8081 --server.servlet.context-path=/test"' > /test-service/spring-boot-app.conf -start_service -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-log-folder.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-log-folder.sh deleted file mode 100755 index da1f7b11c10..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-log-folder.sh +++ /dev/null @@ -1,8 +0,0 @@ -source ./test-functions.sh -mkdir ./pid -install_service -echo 'LOG_FOLDER=log' > /test-service/spring-boot-app.conf -mkdir -p /test-service/log -start_service -await_app -[[ -s /test-service/log/spring-boot-app.log ]] && echo "Log written" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-pid-folder.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-pid-folder.sh deleted file mode 100755 index a46d67b8a2a..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-relative-pid-folder.sh +++ /dev/null @@ -1,10 +0,0 @@ -source ./test-functions.sh -install_service -mkdir /test-service/pid -echo 'PID_FOLDER=pid' > /test-service/spring-boot-app.conf -start_service -echo "PID: $(cat /test-service/pid/spring-boot-app/spring-boot-app.pid)" -await_app -curl -s http://127.0.0.1:8080/ -status_service -stop_service diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-invalid-user.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-invalid-user.sh deleted file mode 100644 index f6384046dcd..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-invalid-user.sh +++ /dev/null @@ -1,7 +0,0 @@ -source ./test-functions.sh -install_service - -echo 'RUN_AS_USER=johndoe' > /test-service/spring-boot-app.conf - -start_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-preferred-to-jar-owner.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-preferred-to-jar-owner.sh deleted file mode 100644 index 730b8197bb9..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-preferred-to-jar-owner.sh +++ /dev/null @@ -1,13 +0,0 @@ -source ./test-functions.sh -install_service - -useradd wagner -echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf - -useradd phil -chown phil /test-service/spring-boot-app.jar - -start_service -await_app - -ls -la /var/log/spring-boot-app.log diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-root-required.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-root-required.sh deleted file mode 100644 index 3cd83374e22..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user-root-required.sh +++ /dev/null @@ -1,9 +0,0 @@ -source ./test-functions.sh -install_service - -useradd wagner -echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf -echo "JAVA_HOME='$JAVA_HOME'" >> /test-service/spring-boot-app.conf - -su - wagner -c "$(which service) spring-boot-app start" -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user.sh deleted file mode 100644 index 6be8eee0f0c..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-run-as-user.sh +++ /dev/null @@ -1,10 +0,0 @@ -source ./test-functions.sh -install_service - -useradd wagner -echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf - -start_service -await_app - -ls -la /var/log/spring-boot-app.log diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-command-line-argument.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-command-line-argument.sh deleted file mode 100755 index 2adb76da3fc..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-command-line-argument.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -install_service -start_service --server.port=8081 -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-java-opt.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-java-opt.sh deleted file mode 100755 index a0445b8224b..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-java-opt.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'JAVA_OPTS=-Dserver.port=8081' > /test-service/spring-boot-app.conf -start_service -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-run-arg.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-run-arg.sh deleted file mode 100755 index 0d61c5d1544..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-single-run-arg.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -echo 'RUN_ARGS=--server.port=8081' > /test-service/spring-boot-app.conf -start_service -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-use-of-start-stop-daemon-disabled.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-use-of-start-stop-daemon-disabled.sh deleted file mode 100755 index 2f2bd3dfadc..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/launch-with-use-of-start-stop-daemon-disabled.sh +++ /dev/null @@ -1,7 +0,0 @@ -source ./test-functions.sh -chmod -x $(type -p start-stop-daemon) -install_service -echo 'USE_START_STOP_DAEMON=false' > /test-service/spring-boot-app.conf -start_service -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-changed-when-created.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-changed-when-created.sh deleted file mode 100755 index 5cc9eb46fc6..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-changed-when-created.sh +++ /dev/null @@ -1,9 +0,0 @@ -source ./test-functions.sh -install_service -echo 'LOG_FOLDER=log' > /test-service/spring-boot-app.conf -mkdir -p /test-service/log -useradd andy -chown andy /test-service/spring-boot-app.jar -start_service -await_app -ls -al /test-service/log/spring-boot-app.log diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-unchanged-when-exists.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-unchanged-when-exists.sh deleted file mode 100755 index 685e1e6100f..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership-is-unchanged-when-exists.sh +++ /dev/null @@ -1,11 +0,0 @@ -source ./test-functions.sh -install_service -echo 'LOG_FOLDER=log' > /test-service/spring-boot-app.conf -mkdir -p /test-service/log -touch /test-service/log/spring-boot-app.log -chmod a+w /test-service/log/spring-boot-app.log -useradd andy -chown andy /test-service/spring-boot-app.jar -start_service -await_app -ls -al /test-service/log/spring-boot-app.log diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership.sh deleted file mode 100755 index 919c33e3809..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/log-file-ownership.sh +++ /dev/null @@ -1,20 +0,0 @@ -source ./test-functions.sh -install_service - -chmod o+w /var/log - -useradd phil -mkdir /phil-files -chown phil /phil-files - -useradd andy -chown andy /test-service/spring-boot-app.jar - -start_service -stop_service - -su - andy -c "ln -s -f /phil-files /var/log/spring-boot-app.log" - -start_service - -ls -ld /phil-files diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-file-ownership.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-file-ownership.sh deleted file mode 100755 index 891bb935fa4..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-file-ownership.sh +++ /dev/null @@ -1,18 +0,0 @@ -source ./test-functions.sh -install_service - -useradd phil -mkdir /phil-files -chown phil /phil-files - -useradd andy -chown andy /test-service/spring-boot-app.jar - -start_service -stop_service - -su - andy -c "ln -s /phil-files /var/run/spring-boot-app/spring-boot-app.pid" - -start_service - -ls -ld /phil-files diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-folder-ownership.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-folder-ownership.sh deleted file mode 100755 index c6b7d19c093..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/pid-folder-ownership.sh +++ /dev/null @@ -1,17 +0,0 @@ -source ./test-functions.sh -install_service - -chmod o+w /var/run - -useradd phil -mkdir /phil-files -chown phil /phil-files - -useradd andy -chown andy /test-service/spring-boot-app.jar - -su - andy -c "ln -s -f /phil-files /var/run/spring-boot-app" - -start_service - -ls -ld /phil-files diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-started.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-started.sh deleted file mode 100755 index 017b4c18e84..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-started.sh +++ /dev/null @@ -1,7 +0,0 @@ -source ./test-functions.sh -install_service -start_service -echo "PID1: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" -restart_service -echo "Status: $?" -echo "PID2: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-stopped.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-stopped.sh deleted file mode 100755 index 95fd91c3b44..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/restart-when-stopped.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -install_service -restart_service -echo "Status: $?" -echo "PID: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-started.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-started.sh deleted file mode 100755 index fd9e4f2f6b8..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-started.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -start_service -echo "PID: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" -start_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-stopped.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-stopped.sh deleted file mode 100755 index 427fff4406a..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/start-when-stopped.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -install_service -start_service -echo "Status: $?" -echo "PID: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-killed.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-killed.sh deleted file mode 100755 index 4a9c5f6fe12..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-killed.sh +++ /dev/null @@ -1,8 +0,0 @@ -source ./test-functions.sh -install_service -start_service -pid=$(cat /var/run/spring-boot-app/spring-boot-app.pid) -echo "PID: $pid" -kill -9 $pid -status_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-started.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-started.sh deleted file mode 100755 index 89c1ccc1fb5..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-started.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -install_service -start_service -status_service -echo "Status: $?" -echo "PID: $(cat /var/run/spring-boot-app/spring-boot-app.pid)" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-stopped.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-stopped.sh deleted file mode 100755 index 24ca2253444..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/status-when-stopped.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -install_service -status_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/stop-when-stopped.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/stop-when-stopped.sh deleted file mode 100755 index b74faddbafd..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/stop-when-stopped.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -install_service -stop_service -echo "Status: $?" diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/test-functions.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/test-functions.sh deleted file mode 100644 index cd6b5217dd8..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/init.d/test-functions.sh +++ /dev/null @@ -1,53 +0,0 @@ -await_app() { - if [ -z $1 ] - then - url=http://127.0.0.1:8080 - else - url=$1 - fi - end=$(date +%s) - let "end+=30" - until curl -s $url > /dev/null - do - now=$(date +%s) - if [[ $now -ge $end ]]; then - break - fi - sleep 1 - done -} - -install_service() { - mkdir /test-service - mv /app.jar /test-service/spring-boot-app.jar - chmod +x /test-service/spring-boot-app.jar - ln -s /test-service/spring-boot-app.jar /etc/init.d/spring-boot-app -} - -install_double_link_service() { - mkdir /test-service - mv /app.jar /test-service/ - chmod +x /test-service/app.jar - ln -s /test-service/app.jar /test-service/spring-boot-app.jar - ln -s /test-service/spring-boot-app.jar /etc/init.d/spring-boot-app -} - -start_service() { - service spring-boot-app start $@ -} - -restart_service() { - service spring-boot-app restart -} - -status_service() { - service spring-boot-app status -} - -stop_service() { - service spring-boot-app stop -} - -force_stop_service() { - service spring-boot-app force-stop -} diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/basic-launch.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/basic-launch.sh deleted file mode 100644 index cf6be88597a..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/basic-launch.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -launch_jar -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-debug.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-debug.sh deleted file mode 100644 index b9d1f6fc850..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-debug.sh +++ /dev/null @@ -1,5 +0,0 @@ -export DEBUG=true -source ./test-functions.sh -launch_jar -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-jarfile.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-jarfile.sh deleted file mode 100644 index 110ab78f01c..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-jarfile.sh +++ /dev/null @@ -1,6 +0,0 @@ -source ./test-functions.sh -cp app.jar app-another.jar -export JARFILE=app-another.jar -launch_jar -await_app -curl -s http://127.0.0.1:8080/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-command-line-arguments.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-command-line-arguments.sh deleted file mode 100755 index 6a97eab32a2..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-command-line-arguments.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -launch_jar --server.port=8081 --server.servlet.context-path=/test -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-java-opts.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-java-opts.sh deleted file mode 100755 index 02f376c0bee..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-java-opts.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -echo 'JAVA_OPTS="-Dserver.port=8081 -Dserver.servlet.context-path=/test"' > app.conf -launch_jar -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-run-args.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-run-args.sh deleted file mode 100755 index aa610e08b5a..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-multiple-run-args.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -echo 'RUN_ARGS="--server.port=8081 --server.servlet.context-path=/test"' > app.conf -launch_jar -await_app http://127.0.0.1:8081/test/ -curl -s http://127.0.0.1:8081/test/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-command-line-argument.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-command-line-argument.sh deleted file mode 100755 index d1be39e8492..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-command-line-argument.sh +++ /dev/null @@ -1,4 +0,0 @@ -source ./test-functions.sh -launch_jar --server.port=8081 -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-java-opt.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-java-opt.sh deleted file mode 100755 index 110c2ec9e9e..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-java-opt.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -echo 'JAVA_OPTS=-Dserver.port=8081' > app.conf -launch_jar -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-run-arg.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-run-arg.sh deleted file mode 100755 index 63f92a886ee..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/launch-with-single-run-arg.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ./test-functions.sh -echo 'RUN_ARGS=--server.port=8081' > app.conf -launch_jar -await_app http://127.0.0.1:8081/ -curl -s http://127.0.0.1:8081/ diff --git a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/test-functions.sh b/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/test-functions.sh deleted file mode 100644 index aa6ea03e1dd..00000000000 --- a/integration-test/spring-boot-launch-script-integration-tests/src/dockerTest/resources/scripts/jar/test-functions.sh +++ /dev/null @@ -1,22 +0,0 @@ -await_app() { - if [ -z $1 ] - then - url=http://127.0.0.1:8080 - else - url=$1 - fi - end=$(date +%s) - let "end+=30" - until curl -s $url > /dev/null - do - now=$(date +%s) - if [[ $now -ge $end ]]; then - break - fi - sleep 1 - done -} - -launch_jar() { - ./app.jar $@ & -} diff --git a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/DefaultLaunchScript.java b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/DefaultLaunchScript.java deleted file mode 100644 index 340d367af07..00000000000 --- a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/DefaultLaunchScript.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.loader.tools; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.jspecify.annotations.Nullable; - -import org.springframework.util.Assert; - -/** - * Default implementation of {@link LaunchScript}. Provides the default Spring Boot launch - * script or can load a specific script File. Also support mustache style template - * expansion of the form {{name:default}}. - * - * @author Phillip Webb - * @author Justin Rosenberg - * @since 1.3.0 - */ -public class DefaultLaunchScript implements LaunchScript { - - private static final int BUFFER_SIZE = 4096; - - private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{\\{(\\w+)(:.*?)?}}(?!})"); - - private static final Set FILE_PATH_KEYS = Collections.singleton("inlinedConfScript"); - - private final String content; - - /** - * Create a new {@link DefaultLaunchScript} instance. - * @param file the source script file or {@code null} to use the default - * @param properties an optional set of script properties used for variable expansion - * @throws IOException if the script cannot be loaded - */ - public DefaultLaunchScript(@Nullable File file, @Nullable Map properties) throws IOException { - String content = loadContent(file); - this.content = expandPlaceholders(content, properties); - } - - private String loadContent(@Nullable File file) throws IOException { - if (file == null) { - InputStream stream = getClass().getResourceAsStream("launch.script"); - Assert.state(stream != null, "Unable to load resource 'launch.script'"); - return loadContent(stream); - } - return loadContent(new FileInputStream(file)); - } - - private String loadContent(InputStream inputStream) throws IOException { - try (inputStream) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - copy(inputStream, outputStream); - return outputStream.toString(StandardCharsets.UTF_8); - } - } - - private void copy(InputStream inputStream, OutputStream outputStream) throws IOException { - byte[] buffer = new byte[BUFFER_SIZE]; - int bytesRead; - while ((bytesRead = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, bytesRead); - } - outputStream.flush(); - } - - private String expandPlaceholders(String content, @Nullable Map properties) throws IOException { - StringBuilder expanded = new StringBuilder(); - Matcher matcher = PLACEHOLDER_PATTERN.matcher(content); - while (matcher.find()) { - String name = matcher.group(1); - final String value; - String defaultValue = matcher.group(2); - if (properties != null && properties.containsKey(name)) { - Object propertyValue = properties.get(name); - if (FILE_PATH_KEYS.contains(name)) { - value = parseFilePropertyValue(propertyValue); - } - else { - value = propertyValue.toString(); - } - } - else { - value = (defaultValue != null) ? defaultValue.substring(1) : matcher.group(0); - } - matcher.appendReplacement(expanded, value.replace("$", "\\$")); - } - matcher.appendTail(expanded); - return expanded.toString(); - } - - private String parseFilePropertyValue(Object propertyValue) throws IOException { - if (propertyValue instanceof File file) { - return loadContent(file); - } - return loadContent(new File(propertyValue.toString())); - } - - @Override - public byte[] toByteArray() { - return this.content.getBytes(StandardCharsets.UTF_8); - } - -} diff --git a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java index 468cdaef2cd..471e7226ff6 100644 --- a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java +++ b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java @@ -57,31 +57,14 @@ public class JarWriter extends AbstractJarWriter implements AutoCloseable { /** * Create a new {@link JarWriter} instance. * @param file the file to write - * @param launchScript an optional launch script to prepend to the front of the jar - * @throws IOException if the file cannot be opened - * @throws FileNotFoundException if the file cannot be found - */ - public JarWriter(File file, @Nullable LaunchScript launchScript) throws FileNotFoundException, IOException { - this(file, launchScript, null); - } - - /** - * Create a new {@link JarWriter} instance. - * @param file the file to write - * @param launchScript an optional launch script to prepend to the front of the jar * @param lastModifiedTime an optional last modified time to apply to the written * entries * @throws IOException if the file cannot be opened * @throws FileNotFoundException if the file cannot be found - * @since 2.3.0 + * @since 4.0.0 */ - public JarWriter(File file, @Nullable LaunchScript launchScript, @Nullable FileTime lastModifiedTime) - throws FileNotFoundException, IOException { + public JarWriter(File file, @Nullable FileTime lastModifiedTime) throws FileNotFoundException, IOException { this.jarOutputStream = new JarArchiveOutputStream(new FileOutputStream(file)); - if (launchScript != null) { - this.jarOutputStream.writePreamble(launchScript.toByteArray()); - file.setExecutable(true); - } this.jarOutputStream.setEncoding("UTF-8"); this.lastModifiedTime = lastModifiedTime; } diff --git a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/LaunchScript.java b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/LaunchScript.java deleted file mode 100644 index dcce60a63d9..00000000000 --- a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/LaunchScript.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.loader.tools; - -/** - * A script that can be prepended to the front of a JAR file to make it executable. - * - * @author Phillip Webb - * @since 1.3.0 - */ -@FunctionalInterface -public interface LaunchScript { - - /** - * The content of the launch script as a byte array. - * @return the script bytes - */ - byte[] toByteArray(); - -} diff --git a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java index 2d0533f5cad..1f3f6d31258 100644 --- a/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java +++ b/loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java @@ -101,28 +101,13 @@ public class Repackager extends Packager { * {@literal java -jar}'. * @param destination the destination file (may be the same as the source) * @param libraries the libraries required to run the archive - * @param launchScript an optional launch script prepended to the front of the jar - * @throws IOException if the file cannot be repackaged - * @since 1.3.0 - */ - public void repackage(File destination, Libraries libraries, @Nullable LaunchScript launchScript) - throws IOException { - repackage(destination, libraries, launchScript, null); - } - - /** - * Repackage to the given destination so that it can be launched using ' - * {@literal java -jar}'. - * @param destination the destination file (may be the same as the source) - * @param libraries the libraries required to run the archive - * @param launchScript an optional launch script prepended to the front of the jar * @param lastModifiedTime an optional last modified time to apply to the archive and * its contents * @throws IOException if the file cannot be repackaged - * @since 2.3.0 + * @since 4.0.0 */ - public void repackage(File destination, Libraries libraries, @Nullable LaunchScript launchScript, - @Nullable FileTime lastModifiedTime) throws IOException { + public void repackage(File destination, Libraries libraries, @Nullable FileTime lastModifiedTime) + throws IOException { Assert.isTrue(destination != null && !destination.isDirectory(), "Invalid destination"); getLayout(); // get layout early destination = destination.getAbsoluteFile(); @@ -139,7 +124,7 @@ public class Repackager extends Packager { destination.delete(); try { try (JarFile sourceJar = new JarFile(workingSource)) { - repackage(sourceJar, destination, libraries, launchScript, lastModifiedTime); + repackage(sourceJar, destination, libraries, lastModifiedTime); } } finally { @@ -150,8 +135,8 @@ public class Repackager extends Packager { } private void repackage(JarFile sourceJar, File destination, Libraries libraries, - @Nullable LaunchScript launchScript, @Nullable FileTime lastModifiedTime) throws IOException { - try (JarWriter writer = new JarWriter(destination, launchScript, lastModifiedTime)) { + @Nullable FileTime lastModifiedTime) throws IOException { + try (JarWriter writer = new JarWriter(destination, lastModifiedTime)) { write(sourceJar, libraries, writer, lastModifiedTime != null); } if (lastModifiedTime != null) { diff --git a/loader/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script b/loader/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script deleted file mode 100755 index ce3115c4371..00000000000 --- a/loader/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script +++ /dev/null @@ -1,309 +0,0 @@ -#!/bin/bash -# -# . ____ _ __ _ _ -# /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ -# ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ -# \\/ ___)| |_)| | | | | || (_| | ) ) ) ) -# ' |____| .__|_| |_|_| |_\__, | / / / / -# =========|_|==============|___/=/_/_/_/ -# :: Spring Boot Startup Script :: -# - -### BEGIN INIT INFO -# Provides: {{initInfoProvides:spring-boot-application}} -# Required-Start: {{initInfoRequiredStart:$remote_fs $syslog $network}} -# Required-Stop: {{initInfoRequiredStop:$remote_fs $syslog $network}} -# Default-Start: {{initInfoDefaultStart:2 3 4 5}} -# Default-Stop: {{initInfoDefaultStop:0 1 6}} -# Short-Description: {{initInfoShortDescription:Spring Boot Application}} -# Description: {{initInfoDescription:Spring Boot Application}} -# chkconfig: {{initInfoChkconfig:2345 99 01}} -### END INIT INFO - -[[ -n "$DEBUG" ]] && set -x - -# Initialize variables that cannot be provided by a .conf file -WORKING_DIR="$(pwd)" -# shellcheck disable=SC2153 -[[ -n "$JARFILE" ]] && jarfile="$JARFILE" -[[ -n "$APP_NAME" ]] && identity="$APP_NAME" - -# Follow symlinks to find the real jar and detect init.d script -cd "$(dirname "$0")" || exit 1 -[[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0") -while [[ -L "$jarfile" ]]; do - if [[ "$jarfile" =~ init\.d ]]; then - init_script=$(basename "$jarfile") - else - configfile="${jarfile%.*}.conf" - # shellcheck source=/dev/null - [[ -r ${configfile} ]] && source "${configfile}" - fi - jarfile=$(readlink "$jarfile") - cd "$(dirname "$jarfile")" || exit 1 - jarfile=$(pwd)/$(basename "$jarfile") -done -jarfolder="$( (cd "$(dirname "$jarfile")" && pwd -P) )" -cd "$WORKING_DIR" || exit 1 - -# Inline script specified in build properties -{{inlinedConfScript:}} - -# Source any config file -configfile="$(basename "${jarfile%.*}.conf")" - -# Initialize CONF_FOLDER location defaulting to jarfolder -[[ -z "$CONF_FOLDER" ]] && CONF_FOLDER="{{confFolder:${jarfolder}}}" -# shellcheck source=/dev/null -[[ -r "${CONF_FOLDER}/${configfile}" ]] && source "${CONF_FOLDER}/${configfile}" - -# ANSI Colors -echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; } -echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; } -echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; } - -# Initialize PID/LOG locations if they weren't provided by the config file -[[ -z "$PID_FOLDER" ]] && PID_FOLDER="{{pidFolder:/var/run}}" -[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="{{logFolder:/var/log}}" -! [[ "$PID_FOLDER" == /* ]] && PID_FOLDER="$(dirname "$jarfile")"/"$PID_FOLDER" -! [[ "$LOG_FOLDER" == /* ]] && LOG_FOLDER="$(dirname "$jarfile")"/"$LOG_FOLDER" -! [[ -x "$PID_FOLDER" ]] && echoYellow "PID_FOLDER $PID_FOLDER does not exist. Falling back to /tmp" && PID_FOLDER="/tmp" -! [[ -x "$LOG_FOLDER" ]] && echoYellow "LOG_FOLDER $LOG_FOLDER does not exist. Falling back to /tmp" && LOG_FOLDER="/tmp" - -# Set up defaults -[[ -z "$MODE" ]] && MODE="{{mode:auto}}" # modes are "auto", "service" or "run" -[[ -z "$USE_START_STOP_DAEMON" ]] && USE_START_STOP_DAEMON="{{useStartStopDaemon:true}}" - -# Create an identity for log/pid files -if [[ -z "$identity" ]]; then - if [[ -n "$init_script" ]]; then - identity="${init_script}" - else - identity=$(basename "${jarfile%.*}")_${jarfolder//\//} - fi -fi - -# Initialize log file name if not provided by the config file -[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="{{logFilename:${identity}.log}}" - -# Initialize stop wait time if not provided by the config file -[[ -z "$STOP_WAIT_TIME" ]] && STOP_WAIT_TIME="{{stopWaitTime:60}}" - -# Utility functions -checkPermissions() { - touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; return 4; } - touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; return 4; } -} - -isRunning() { - ps -p "$1" &> /dev/null -} - -await_file() { - end=$(date +%s) - let "end+=10" - while [[ ! -s "$1" ]] - do - now=$(date +%s) - if [[ $now -ge $end ]]; then - break - fi - sleep 1 - done -} - -# Determine the script mode -action="run" -if [[ "$MODE" == "auto" && -n "$init_script" ]] || [[ "$MODE" == "service" ]]; then - action="$1" - shift -fi - -# Build the pid and log filenames -PID_FOLDER="$PID_FOLDER/${identity}" -pid_file="$PID_FOLDER/{{pidFilename:${identity}.pid}}" -log_file="$LOG_FOLDER/$LOG_FILENAME" - -# Determine the user to run as if we are root -# shellcheck disable=SC2012 -[[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}') - -# Ensure the user actually exists -id -u "$run_user" &> /dev/null || unset run_user - -# Run as user specified in RUN_AS_USER -if [[ -n "$RUN_AS_USER" ]]; then - if ! [[ "$action" =~ ^(status|run)$ ]]; then - id -u "$RUN_AS_USER" || { - echoRed "Cannot run as '$RUN_AS_USER': no such user" - exit 2 - } - [[ $(id -u) == 0 ]] || { - echoRed "Cannot run as '$RUN_AS_USER': current user is not root" - exit 4 - } - fi - run_user="$RUN_AS_USER" -fi - -# Issue a warning if the application will run as root -[[ $(id -u ${run_user}) == "0" ]] && { echoYellow "Application is running as root (UID 0). This is considered insecure."; } - -# Find Java -if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then - javaexe="$JAVA_HOME/bin/java" -elif type -p java > /dev/null 2>&1; then - javaexe=$(type -p java) -elif [[ -x "/usr/bin/java" ]]; then - javaexe="/usr/bin/java" -else - echo "Unable to find Java" - exit 1 -fi - -arguments=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar "$jarfile" $RUN_ARGS "$@") - -# Action functions -start() { - if [[ -f "$pid_file" ]]; then - pid=$(cat "$pid_file") - isRunning "$pid" && { echoYellow "Already running [$pid]"; return 0; } - fi - do_start "$@" -} - -do_start() { - working_dir=$(dirname "$jarfile") - pushd "$working_dir" > /dev/null - if [[ ! -e "$PID_FOLDER" ]]; then - mkdir -p "$PID_FOLDER" &> /dev/null - if [[ -n "$run_user" ]]; then - chown "$run_user" "$PID_FOLDER" - fi - fi - if [[ ! -e "$log_file" ]]; then - touch "$log_file" &> /dev/null - if [[ -n "$run_user" ]]; then - chown "$run_user" "$log_file" - fi - fi - if [[ -n "$run_user" ]]; then - checkPermissions || return $? - if [ $USE_START_STOP_DAEMON = true ] && type start-stop-daemon > /dev/null 2>&1; then - start-stop-daemon --start --quiet \ - --chuid "$run_user" \ - --name "$identity" \ - --make-pidfile --pidfile "$pid_file" \ - --background --no-close \ - --startas "$javaexe" \ - --chdir "$working_dir" \ - -- "${arguments[@]}" \ - >> "$log_file" 2>&1 - await_file "$pid_file" - else - su -s /bin/sh -c "$javaexe $(printf "\"%s\" " "${arguments[@]}") >> \"$log_file\" 2>&1 & echo \$!" "$run_user" > "$pid_file" - fi - pid=$(cat "$pid_file") - else - checkPermissions || return $? - "$javaexe" "${arguments[@]}" >> "$log_file" 2>&1 & - pid=$! - disown $pid - echo "$pid" > "$pid_file" - fi - [[ -z $pid ]] && { echoRed "Failed to start"; return 1; } - echoGreen "Started [$pid]" -} - -stop() { - working_dir=$(dirname "$jarfile") - pushd "$working_dir" > /dev/null - [[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; } - pid=$(cat "$pid_file") - isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; } - do_stop "$pid" "$pid_file" -} - -do_stop() { - kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; } - for ((i = 1; i <= STOP_WAIT_TIME; i++)); do - isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; } - [[ $i -eq STOP_WAIT_TIME/2 ]] && kill "$1" &> /dev/null - sleep 1 - done - echoRed "Unable to kill process $1"; - return 1; -} - -force_stop() { - [[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; } - pid=$(cat "$pid_file") - isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; } - do_force_stop "$pid" "$pid_file" -} - -do_force_stop() { - kill -9 "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; } - for ((i = 1; i <= STOP_WAIT_TIME; i++)); do - isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; } - [[ $i -eq STOP_WAIT_TIME/2 ]] && kill -9 "$1" &> /dev/null - sleep 1 - done - echoRed "Unable to kill process $1"; - return 1; -} - -restart() { - stop && start -} - -force_reload() { - working_dir=$(dirname "$jarfile") - pushd "$working_dir" > /dev/null - [[ -f $pid_file ]] || { echoRed "Not running (pidfile not found)"; return 7; } - pid=$(cat "$pid_file") - rm -f "$pid_file" - isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 7; } - do_stop "$pid" "$pid_file" - do_start -} - -status() { - working_dir=$(dirname "$jarfile") - pushd "$working_dir" > /dev/null - [[ -f "$pid_file" ]] || { echoRed "Not running"; return 3; } - pid=$(cat "$pid_file") - isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 1; } - echoGreen "Running [$pid]" - return 0 -} - -run() { - pushd "$(dirname "$jarfile")" > /dev/null - "$javaexe" "${arguments[@]}" - result=$? - popd > /dev/null - return "$result" -} - -# Call the appropriate action function -case "$action" in -start) - start "$@"; exit $?;; -stop) - stop "$@"; exit $?;; -force-stop) - force_stop "$@"; exit $?;; -restart) - restart "$@"; exit $?;; -force-reload) - force_reload "$@"; exit $?;; -status) - status "$@"; exit $?;; -run) - run "$@"; exit $?;; -*) - echo "Usage: $0 {start|stop|force-stop|restart|force-reload|status|run}"; exit 1; -esac - -exit 0 diff --git a/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java b/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java deleted file mode 100644 index 5b06a71fa60..00000000000 --- a/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2012-present 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 - * - * https://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.loader.tools; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import org.springframework.util.FileCopyUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link DefaultLaunchScript}. - * - * @author Phillip Webb - * @author Andy Wilkinson - * @author Justin Rosenberg - */ -class DefaultLaunchScriptTests { - - @TempDir - @SuppressWarnings("NullAway.Init") - File tempDir; - - @Test - void loadsDefaultScript() throws Exception { - DefaultLaunchScript script = new DefaultLaunchScript(null, null); - String content = new String(script.toByteArray()); - assertThat(content).contains("Spring Boot Startup Script"); - } - - @Test - void logFilenameCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("logFilename"); - } - - @Test - void pidFilenameCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("pidFilename"); - } - - @Test - void initInfoProvidesCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoProvides"); - } - - @Test - void initInfoRequiredStartCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoRequiredStart"); - } - - @Test - void initInfoRequiredStopCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoRequiredStop"); - } - - @Test - void initInfoDefaultStartCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoDefaultStart"); - } - - @Test - void initInfoDefaultStopCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoDefaultStop"); - } - - @Test - void initInfoShortDescriptionCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoShortDescription"); - } - - @Test - void initInfoDescriptionCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoDescription"); - } - - @Test - void initInfoChkconfigCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("initInfoChkconfig"); - } - - @Test - void modeCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("mode"); - } - - @Test - void useStartStopDaemonCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("useStartStopDaemon"); - } - - @Test - void logFolderCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("logFolder"); - } - - @Test - void pidFolderCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("pidFolder"); - } - - @Test - void confFolderCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("confFolder"); - } - - @Test - void stopWaitTimeCanBeReplaced() throws Exception { - assertThatPlaceholderCanBeReplaced("stopWaitTime"); - } - - @Test - void inlinedConfScriptFileLoad() throws IOException { - DefaultLaunchScript script = new DefaultLaunchScript(null, - createProperties("inlinedConfScript:src/test/resources/example.script")); - String content = new String(script.toByteArray()); - assertThat(content).contains("FOO=BAR"); - } - - @Test - void defaultForUseStartStopDaemonIsTrue() throws Exception { - DefaultLaunchScript script = new DefaultLaunchScript(null, null); - String content = new String(script.toByteArray()); - assertThat(content).contains("USE_START_STOP_DAEMON=\"true\""); - } - - @Test - void defaultForModeIsAuto() throws Exception { - DefaultLaunchScript script = new DefaultLaunchScript(null, null); - String content = new String(script.toByteArray()); - assertThat(content).contains("MODE=\"auto\""); - } - - @Test - void defaultForStopWaitTimeIs60() throws Exception { - DefaultLaunchScript script = new DefaultLaunchScript(null, null); - String content = new String(script.toByteArray()); - assertThat(content).contains("STOP_WAIT_TIME=\"60\""); - } - - @Test - void loadFromFile() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("ABC".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, null); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("ABC"); - } - - @Test - void expandVariables() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("h{{a}}ll{{b}}".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, createProperties("a:e", "b:o")); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("hello"); - } - - @Test - void expandVariablesMultiLine() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("h{{a}}l\nl{{b}}".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, createProperties("a:e", "b:o")); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("hel\nlo"); - } - - @Test - void expandVariablesWithDefaults() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("h{{a:e}}ll{{b:o}}".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, null); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("hello"); - } - - @Test - void expandVariablesCanDefaultToBlank() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("s{{p:}}{{r:}}ing".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, null); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("sing"); - } - - @Test - void expandVariablesWithDefaultsOverride() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("h{{a:e}}ll{{b:o}}".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, createProperties("a:a")); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("hallo"); - } - - @Test - void expandVariablesMissingAreUnchanged() throws Exception { - File file = new File(this.tempDir, "script"); - FileCopyUtils.copy("h{{a}}ll{{b}}".getBytes(), file); - DefaultLaunchScript script = new DefaultLaunchScript(file, null); - String content = new String(script.toByteArray()); - assertThat(content).isEqualTo("h{{a}}ll{{b}}"); - } - - private void assertThatPlaceholderCanBeReplaced(String placeholder) throws Exception { - DefaultLaunchScript script = new DefaultLaunchScript(null, createProperties(placeholder + ":__test__")); - String content = new String(script.toByteArray()); - assertThat(content).contains("__test__"); - } - - private Map createProperties(String... pairs) { - Map properties = new HashMap<>(); - for (String pair : pairs) { - String[] keyValue = pair.split(":"); - properties.put(keyValue[0], keyValue[1]); - } - return properties; - } - -} diff --git a/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java b/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java index c84d389605d..3c050203bff 100644 --- a/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java +++ b/loader/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java @@ -19,9 +19,7 @@ package org.springframework.boot.loader.tools; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.attribute.FileTime; -import java.nio.file.attribute.PosixFilePermission; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.ArrayList; @@ -156,30 +154,6 @@ class RepackagerTests extends AbstractPackagerTests { assertThat(hasLauncherClasses(this.destination)).isTrue(); } - @Test - void addLauncherScript() throws Exception { - this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); - File source = this.testJarFile.getFile(); - Repackager repackager = createRepackager(source, true); - LaunchScript script = new MockLauncherScript("ABC"); - assertThat(this.destination).isNotNull(); - repackager.repackage(this.destination, NO_LIBRARIES, script); - byte[] bytes = FileCopyUtils.copyToByteArray(this.destination); - assertThat(new String(bytes)).startsWith("ABC"); - assertThat(hasLauncherClasses(source)).isFalse(); - assertThat(hasLauncherClasses(this.destination)).isTrue(); - try (ZipFile zipFile = ZipFile.builder().setFile(this.destination).get()) { - assertThat(zipFile.getEntries().hasMoreElements()).isTrue(); - } - try { - assertThat(Files.getPosixFilePermissions(this.destination.toPath())) - .contains(PosixFilePermission.OWNER_EXECUTE); - } - catch (UnsupportedOperationException ex) { - // Probably running the test on Windows - } - } - @Test void allLoaderDirectoriesAndFilesUseSameTimestamp() throws IOException { this.testJarFile.addClass("A.class", ClassWithMainMethod.class); @@ -208,7 +182,7 @@ class RepackagerTests extends AbstractPackagerTests { Repackager repackager = createRepackager(this.testJarFile.getFile(), true); long timestamp = OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli(); assertThat(this.destination).isNotNull(); - repackager.repackage(this.destination, NO_LIBRARIES, null, FileTime.fromMillis(timestamp)); + repackager.repackage(this.destination, NO_LIBRARIES, FileTime.fromMillis(timestamp)); long offsetTimestamp = DefaultTimeZoneOffset.INSTANCE.removeFrom(timestamp); for (ZipArchiveEntry entry : getAllPackagedEntries()) { assertThat(entry.getTime()).isEqualTo(offsetTimestamp); @@ -223,7 +197,7 @@ class RepackagerTests extends AbstractPackagerTests { ClassWithMainMethod.class); Repackager repackager = createRepackager(this.testJarFile.getFile(), true); assertThat(this.destination).isNotNull(); - repackager.repackage(this.destination, NO_LIBRARIES, null, null); + repackager.repackage(this.destination, NO_LIBRARIES, null); stopWatch.stop(); assertThat(stopWatch.getTotalTimeMillis()).isLessThan(5000); } @@ -306,21 +280,6 @@ class RepackagerTests extends AbstractPackagerTests { } } - static class MockLauncherScript implements LaunchScript { - - private final byte[] bytes; - - MockLauncherScript(String script) { - this.bytes = script.getBytes(); - } - - @Override - public byte[] toByteArray() { - return this.bytes; - } - - } - static class TestLayoutFactory implements LayoutFactory { @Override diff --git a/settings.gradle b/settings.gradle index df53ce99d64..0bb7d404b12 100644 --- a/settings.gradle +++ b/settings.gradle @@ -472,7 +472,6 @@ include ":smoke-test:spring-boot-smoke-test-xml" include ":integration-test:spring-boot-actuator-integration-tests" include ":integration-test:spring-boot-configuration-processor-integration-tests" include ":integration-test:spring-boot-integration-tests" -include ":integration-test:spring-boot-launch-script-integration-tests" include ":integration-test:spring-boot-loader-integration-tests" include ":integration-test:spring-boot-server-integration-tests" include ":integration-test:spring-boot-sni-integration-tests"