From e6dc0bc342ee06061668ad34ec54f274def1767c Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 7 May 2025 16:35:40 +0200 Subject: [PATCH] GH-2814 Add version numbers of currently ruunning stream/function Version information is addedc to the standard Spring Boot banner Resolves #2814 --- .../cloud/stream/config/VersionExtractor.java | 82 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 1 + .../src/main/resources/banner.txt | 10 +++ 3 files changed, 93 insertions(+) create mode 100644 core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/VersionExtractor.java create mode 100644 core/spring-cloud-stream/src/main/resources/banner.txt diff --git a/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/VersionExtractor.java b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/VersionExtractor.java new file mode 100644 index 000000000..8499f1bf7 --- /dev/null +++ b/core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/VersionExtractor.java @@ -0,0 +1,82 @@ +/* + * Copyright 2019-2025 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.cloud.stream.config; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.cloud.stream.function.FunctionConfiguration; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.StringUtils; +/** + * + * @author Oleg Zhurakousky + * @since 4.2.x + */ +class VersionExtractor implements EnvironmentPostProcessor { + + protected final Log logger = LogFactory.getLog(getClass()); + + private final Pattern versionPattern = Pattern.compile("(\\d+)\\.{1}(\\d+)\\.{1}(\\d+)(?:\\-{1}(\\w+))?"); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + String streamJarPath = FunctionConfiguration.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + if (logger.isDebugEnabled()) { + logger.debug("Spring Cloud Stream is loaded from: " + streamJarPath); + } + System.setProperty("spring-cloud-stream.version", this.extractVersion(streamJarPath)); + String functionJarPath = FunctionCatalog.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + if (logger.isDebugEnabled()) { + logger.debug("Spring Cloud Function is loaded from: " + streamJarPath); + } + System.setProperty("spring-cloud-function.version", this.extractVersion(functionJarPath)); + } + + private String extractVersion(String jarFilePath) { + try { + if (jarFilePath.endsWith(".jar")) { + Matcher m = versionPattern.matcher(jarFilePath); + if (!m.find()) { + return ""; + } + StringBuilder versionBuilder = new StringBuilder(); + String delimiter = ""; + for (int i = 0; i < m.groupCount();) { + String value = m.group(++i); + if (StringUtils.hasText(value)) { + versionBuilder.append(delimiter); + versionBuilder.append(value); + delimiter = (i + 1 < m.groupCount()) ? "." : "-"; + } + } + return versionBuilder.toString(); + } + } + catch (Throwable e) { + logger.warn("Failed to determine version of: " + jarFilePath, e); + } + return ""; + } +} diff --git a/core/spring-cloud-stream/src/main/resources/META-INF/spring.factories b/core/spring-cloud-stream/src/main/resources/META-INF/spring.factories index 1a92c5655..f5bbee275 100644 --- a/core/spring-cloud-stream/src/main/resources/META-INF/spring.factories +++ b/core/spring-cloud-stream/src/main/resources/META-INF/spring.factories @@ -1,5 +1,6 @@ org.springframework.boot.env.EnvironmentPostProcessor:\ org.springframework.cloud.stream.function.RoutingFunctionEnvironmentPostProcessor,\ +org.springframework.cloud.stream.config.VersionExtractor,\ org.springframework.cloud.stream.config.PollerConfigEnvironmentPostProcessor org.springframework.context.ApplicationContextInitializer:\ org.springframework.cloud.stream.function.PollableSourceInitializer diff --git a/core/spring-cloud-stream/src/main/resources/banner.txt b/core/spring-cloud-stream/src/main/resources/banner.txt new file mode 100644 index 000000000..831aa7f0a --- /dev/null +++ b/core/spring-cloud-stream/src/main/resources/banner.txt @@ -0,0 +1,10 @@ + . ____ _ __ _ _ + /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ +( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ + \\/ ___)| |_)| | | | | || (_| | ) ) ) ) + ' |____| .__|_| |_|_| |_\__, | / / / / + =========|_|==============|___/=/_/_/_/ + + :: Spring Boot :: v${spring-boot.version} + :: Spring Cloud Stream :: v${spring-cloud-stream.version} + :: Spring Cloud Function :: v${spring-cloud-function.version} \ No newline at end of file