This is an automated email from the ASF dual-hosted git repository. matrei pushed a commit to branch banner-versions in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit e03070ec0e7a5751ef796bf51f32934c1774afe9 Author: Mattias Reichel <[email protected]> AuthorDate: Fri Nov 14 12:17:32 2025 +0100 feat: add versions to banner --- .../src/main/resources/grails-banner.txt | 3 +- .../src/main/groovy/grails/boot/GrailsApp.groovy | 4 +- .../main/groovy/grails/boot/GrailsBanner.groovy | 99 ++++++++++++++++++++++ 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/grails-bootstrap/src/main/resources/grails-banner.txt b/grails-bootstrap/src/main/resources/grails-banner.txt index fdc3539439..c6792b01bc 100644 --- a/grails-bootstrap/src/main/resources/grails-banner.txt +++ b/grails-bootstrap/src/main/resources/grails-banner.txt @@ -1,4 +1,3 @@ - > < > ____ _ _ < > / ___|_ __ __ _(_) |___ < @@ -6,4 +5,4 @@ > | |_| | | | (_| | | \__ \ < > \____|_| \__,_|_|_|___/ < > https://grails.apache.org < -> < +> < \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy index 16bc28b2a8..2fd34aee6d 100644 --- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy +++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy @@ -27,12 +27,10 @@ import org.codehaus.groovy.control.CompilationFailedException import org.codehaus.groovy.control.CompilationUnit import org.codehaus.groovy.control.CompilerConfiguration -import org.springframework.boot.ResourceBanner import org.springframework.boot.SpringApplication import org.springframework.boot.web.context.WebServerApplicationContext import org.springframework.context.ConfigurableApplicationContext import org.springframework.core.env.ConfigurableEnvironment -import org.springframework.core.io.ClassPathResource import org.springframework.core.io.ResourceLoader import grails.compiler.ast.ClassInjector @@ -95,7 +93,7 @@ class GrailsApp extends SpringApplication { */ GrailsApp(ResourceLoader resourceLoader, Class<?>... sources) { super(resourceLoader, sources) - banner = new ResourceBanner(new ClassPathResource(GRAILS_BANNER)) + banner = new GrailsBanner(GRAILS_BANNER) } @Override diff --git a/grails-core/src/main/groovy/grails/boot/GrailsBanner.groovy b/grails-core/src/main/groovy/grails/boot/GrailsBanner.groovy new file mode 100644 index 0000000000..107e29315e --- /dev/null +++ b/grails-core/src/main/groovy/grails/boot/GrailsBanner.groovy @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 grails.boot + +import groovy.transform.CompileStatic + +import org.springframework.boot.Banner +import org.springframework.boot.SpringBootVersion +import org.springframework.core.SpringVersion +import org.springframework.core.env.Environment +import org.springframework.core.io.ClassPathResource + +import grails.util.BuildSettings + +@CompileStatic +class GrailsBanner implements Banner { + + private static final int FALLBACK_BANNER_WIDTH = 80 + private static final int VERSIONS_MARGIN = 4 + private static final String VERSIONS_SEPARATOR = ' | ' + + private final String asciiArt + private final Map versions + + GrailsBanner(String grailsBannerFile) { + def bannerResource = new ClassPathResource(grailsBannerFile) + def appNameResolver = { Environment env -> env.getProperty('info.app.name') ?: 'application' } + def appVersionResolver = { Environment env -> env.getProperty('info.app.version') ?: 'unknown' } + asciiArt = bannerResource.exists() ? bannerResource.inputStream.text : '' + versions = [ + (appNameResolver): appVersionResolver, + 'Grails': BuildSettings.grailsVersion, + 'Groovy': GroovySystem.version, + 'JVM': System.getProperty('java.version'), + 'Spring Boot': SpringBootVersion.version, + 'Spring': SpringVersion.version + ] + } + + @Override + void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) { + int bannerWidth = longestLineLength(asciiArt) ?: FALLBACK_BANNER_WIDTH + def versionPairs = versions.collectEntries { + [(resolveValue(it.key, environment)): resolveValue(it.value, environment)] + } + out.println() + out.println(asciiArt) + buildVersionRows(versionPairs, bannerWidth).stream().forEach(out::println) + } + + private static String resolveValue(Object value, Environment environment) { + value instanceof Closure ? value(environment) : value + } + + private static int longestLineLength(String text) { + text.readLines()*.size()?.max() ?: 0 + } + + private static List buildVersionRows(Map versions, int bannerWidth) { + def maxWidth = bannerWidth - VERSIONS_MARGIN * 2 + def rows = [] + def currentRow = new StringBuilder() + def countInRow = 0 + versions.each { + String value = "$it.key: $it.value" + int proposedLength = currentRow.size() + (countInRow > 0 ? VERSIONS_SEPARATOR.size() : 0) + value.size() + boolean wouldOverflow = proposedLength > maxWidth + if (wouldOverflow) { + rows << currentRow.center(bannerWidth) + currentRow.length = 0 + } + if (currentRow.size() > 0) { + currentRow << VERSIONS_SEPARATOR + } + currentRow << value + countInRow++ + } + if (countInRow > 0) { + rows << currentRow.center(bannerWidth) + } + rows + } +}
