├── .gitignore ├── README.md ├── build.gradle ├── config └── checkstyle │ ├── checkstyle-suppressions.xml │ └── checkstyle.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── launch.script ├── settings.gradle └── src ├── main ├── java │ └── io │ │ └── spring │ │ └── bomr │ │ ├── BomrApplication.java │ │ ├── BomrProperties.java │ │ ├── Command.java │ │ ├── Commands.java │ │ ├── UserHomeBomrPropertiesEnvironmentPostProcessor.java │ │ ├── artifacts │ │ ├── ArtifactsCommand.java │ │ ├── ArtifactsCommandArguments.java │ │ ├── ArtifactsConfiguration.java │ │ ├── ArtifactsDeltaCommand.java │ │ ├── ArtifactsDeltaCommandArguments.java │ │ ├── ArtifactsFinder.java │ │ ├── MavenCentralSearchArtifactsFinder.java │ │ └── MavenRepositoryArtifactsFinder.java │ │ ├── github │ │ ├── GitHub.java │ │ ├── GitHubConfiguration.java │ │ ├── GitHubProperties.java │ │ ├── GitHubRepository.java │ │ ├── Milestone.java │ │ ├── StandardGitHub.java │ │ └── StandardGitHubRepository.java │ │ ├── upgrade │ │ ├── Bom.java │ │ ├── BomUpgrader.java │ │ ├── BomVersions.java │ │ ├── InteractiveUpgradeResolver.java │ │ ├── MavenMetadataVersionResolver.java │ │ ├── Module.java │ │ ├── ProhibitedVersions.java │ │ ├── Project.java │ │ ├── ProjectName.java │ │ ├── StringToVersionRangeConverter.java │ │ ├── Upgrade.java │ │ ├── UpgradeCommand.java │ │ ├── UpgradeCommandArguments.java │ │ ├── UpgradeConfiguration.java │ │ ├── UpgradePolicy.java │ │ ├── UpgradeProperties.java │ │ ├── UpgradeResolver.java │ │ ├── VersionResolver.java │ │ └── version │ │ │ ├── AbstractDependencyVersion.java │ │ │ ├── ArtifactVersionDependencyVersion.java │ │ │ ├── CombinedPatchAndQualifierDependencyVersion.java │ │ │ ├── DependencyVersion.java │ │ │ ├── LeadingZeroesDependencyVersion.java │ │ │ ├── NumericQualifierDependencyVersion.java │ │ │ ├── ReleaseTrainDependencyVersion.java │ │ │ └── UnstructuredDependencyVersion.java │ │ └── verify │ │ ├── BomVerifier.java │ │ ├── ManagedDependency.java │ │ ├── MavenInvoker.java │ │ ├── MavenProperties.java │ │ ├── Repository.java │ │ ├── VerifiableBom.java │ │ ├── VerificationConfiguration.java │ │ ├── VerifyCommand.java │ │ ├── VerifyCommandArguments.java │ │ └── VerifyProperties.java └── resources │ ├── META-INF │ └── spring.factories │ └── templates │ └── bom-dependencies.mustache └── test ├── java └── io │ └── spring │ └── bomr │ ├── CommandsTests.java │ ├── artifacts │ ├── MavenCentralSearchArtifactsFinderTests.java │ └── MavenRepositoryArtifactsFinderTests.java │ └── upgrade │ ├── BomVersionsTests.java │ ├── MavenMetadataVersionResolverTests.java │ ├── UpgradePolicyTests.java │ └── version │ ├── ArtifactVersionDependencyVersionTests.java │ ├── DependencyVersionTests.java │ ├── NumericQualifierDependencyVersionTests.java │ └── ReleaseTrainDependencyVersionTests.java └── resources ├── artifacts └── org │ ├── infinispan │ ├── page1.json │ ├── page2.json │ ├── page3.json │ ├── page4.json │ ├── page5.json │ └── page6.json │ └── quartz-scheduler │ ├── index.html │ ├── internal │ └── index.html │ ├── quartz-backward-compat │ └── index.html │ ├── quartz-commonj │ └── index.html │ ├── quartz-jboss │ └── index.html │ ├── quartz-jobs │ ├── 2.3.0 │ │ └── quartz-jobs-2.3.0.jar │ └── index.html │ ├── quartz-oracle │ └── index.html │ ├── quartz-parent │ └── index.html │ ├── quartz-weblogic │ └── index.html │ └── quartz │ ├── 2.3.0 │ └── quartz-2.3.0.jar │ └── index.html ├── repo1-maven-metadata.xml ├── repo2-maven-metadata.xml ├── spring-boot.bom └── spring-core-maven-metadata.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .classpath 3 | .factorypath 4 | .project 5 | .settings 6 | /bin/ 7 | 8 | # IntelliJ IDEA 9 | .idea 10 | *.iml 11 | 12 | /build/ 13 | /.gradle/ -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | classpath 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.14' 7 | } 8 | } 9 | 10 | plugins { 11 | id 'checkstyle' 12 | id 'java' 13 | id 'org.springframework.boot' version '2.2.2.RELEASE' 14 | } 15 | 16 | apply plugin: 'io.spring.dependency-management' 17 | apply plugin: 'io.spring.javaformat' 18 | 19 | repositories { 20 | mavenCentral() 21 | } 22 | 23 | group = 'io.spring.bomr' 24 | version = '0.1.0-SNAPSHOT' 25 | 26 | sourceCompatibility = '1.8' 27 | 28 | dependencyManagement { 29 | dependencies { 30 | dependency 'com.jayway.jsonpath:json-path:2.4.0' 31 | dependency 'com.samskivert:jmustache:1.14' 32 | dependency 'io.spring.javaformat:spring-javaformat-checkstyle:0.0.14' 33 | dependency 'net.sf.jopt-simple:jopt-simple:5.0.4' 34 | dependency 'org.apache.maven:maven-artifact:3.6.0' 35 | dependency 'org.apache.maven.resolver:maven-resolver-util:1.3.1' 36 | dependency 'org.apache.maven.shared:maven-invoker:3.0.1' 37 | } 38 | } 39 | 40 | dependencies { 41 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 42 | 43 | checkstyle 'io.spring.javaformat:spring-javaformat-checkstyle' 44 | 45 | compile 'com.fasterxml.jackson.core:jackson-databind' 46 | compile 'com.jayway.jsonpath:json-path' 47 | compile 'com.samskivert:jmustache' 48 | compile 'net.sf.jopt-simple:jopt-simple' 49 | compile 'org.apache.maven:maven-artifact' 50 | compile 'org.apache.maven.resolver:maven-resolver-util' 51 | compile 'org.apache.maven.shared:maven-invoker' 52 | compile 'org.springframework:spring-web' 53 | compile 'org.springframework.boot:spring-boot-starter' 54 | 55 | testCompile 'org.springframework.boot:spring-boot-starter-test' 56 | } 57 | 58 | bootJar { 59 | launchScript { 60 | script = file('launch.script') 61 | } 62 | } 63 | 64 | tasks.withType(JavaCompile) { 65 | options.encoding = 'UTF-8' 66 | } 67 | 68 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/bomr/91a916478d46d89ac803b9c37155d0fbba84407d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /launch.script: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [[ -n "$DEBUG" ]] && set -x 4 | 5 | working_directory="$(pwd)" 6 | 7 | # Follow symlinks to find the real jar 8 | cd "$(dirname "$0")" || exit 1 9 | [[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0") 10 | while [[ -L "$jarfile" ]]; do 11 | jarfile=$(readlink "$jarfile") 12 | cd "$(dirname "$jarfile")" || exit 1 13 | jarfile=$(pwd)/$(basename "$jarfile") 14 | done 15 | 16 | cd "$working_directory" 17 | 18 | # Find Java 19 | if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then 20 | javaexe="$JAVA_HOME/bin/java" 21 | elif type -p java > /dev/null 2>&1; then 22 | javaexe=$(type -p java) 23 | elif [[ -x "/usr/bin/java" ]]; then 24 | javaexe="/usr/bin/java" 25 | else 26 | echo "Unable to find Java" 27 | exit 1 28 | fi 29 | 30 | arguments=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar "$jarfile" $RUN_ARGS "$@") 31 | 32 | "$javaexe" "${arguments[@]}" 33 | exit $? 34 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'bomr' 2 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/BomrApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | import java.util.Arrays; 20 | 21 | import org.springframework.boot.Banner.Mode; 22 | import org.springframework.boot.autoconfigure.SpringBootApplication; 23 | import org.springframework.boot.builder.SpringApplicationBuilder; 24 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 25 | import org.springframework.context.ConfigurableApplicationContext; 26 | 27 | /** 28 | * Main entry point for Bomr. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | @SpringBootApplication 33 | @EnableConfigurationProperties(BomrProperties.class) 34 | public class BomrApplication { 35 | 36 | public static void main(String[] args) { 37 | ConfigurableApplicationContext context = new SpringApplicationBuilder(BomrApplication.class) 38 | .properties("logging.level.root=warn", "spring.config.location=file:.bomr/", "spring.config.name=bomr") 39 | .bannerMode(Mode.OFF).run(args); 40 | Commands commands = context.getBean(Commands.class); 41 | if (args.length == 0) { 42 | displayUsage(); 43 | System.err.println(); 44 | displayCommandList(commands); 45 | System.exit(-1); 46 | } 47 | Command command = commands.get(args[0]); 48 | if (command == null) { 49 | System.err.println("bomr: '" + args[0] + "' is not a bomr command"); 50 | System.err.println(); 51 | displayCommandList(commands); 52 | System.exit(-1); 53 | } 54 | else { 55 | command.invoke(Arrays.copyOfRange(args, 1, args.length)); 56 | } 57 | } 58 | 59 | private static void displayUsage() { 60 | System.err.println("Usage: bomr []"); 61 | } 62 | 63 | private static void displayCommandList(Commands commands) { 64 | System.err.println("Commands:"); 65 | System.err.println(); 66 | System.err.println(commands.describe()); 67 | System.err.println(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/BomrProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | import java.io.File; 20 | 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | 23 | /** 24 | * General {@link ConfigurationProperties configuration properties} that are not specific 25 | * to any one command. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | @ConfigurationProperties("bomr") 30 | public class BomrProperties { 31 | 32 | /** 33 | * Location of the pom file to be analyzed by Bomr. 34 | */ 35 | private File bom; 36 | 37 | public File getBom() { 38 | return this.bom; 39 | } 40 | 41 | public void setBom(File bom) { 42 | this.bom = bom; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/Command.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | /** 20 | * A Bomr command. 21 | * 22 | * @author Andy Wilkinson 23 | */ 24 | public interface Command extends Comparable { 25 | 26 | /** 27 | * Returns the name of the command that is used to invoke it from the command line. 28 | * @return the name of the command 29 | */ 30 | String getName(); 31 | 32 | /** 33 | * Returns the description of the command, shown in CLI usage messages. 34 | * @return the description of the command 35 | */ 36 | String getDescription(); 37 | 38 | /** 39 | * Invokes the command using the given {@code args}. 40 | * @param args the args 41 | */ 42 | void invoke(String[] args); 43 | 44 | @Override 45 | default int compareTo(Command command) { 46 | return getName().compareTo(command.getName()); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/Commands.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | import java.io.PrintWriter; 20 | import java.io.StringWriter; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import org.springframework.stereotype.Component; 26 | 27 | /** 28 | * The available {@link Command Commands}. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | @Component 33 | class Commands { 34 | 35 | private final Map commands = new HashMap<>(); 36 | 37 | Commands(List commands) { 38 | commands.forEach((command) -> this.commands.put(command.getName(), command)); 39 | } 40 | 41 | Command get(String name) { 42 | return this.commands.get(name); 43 | } 44 | 45 | String describe() { 46 | int maxLength = this.commands.keySet().stream().map(String::length).max((i1, i2) -> i1.compareTo(i2)).get(); 47 | StringWriter description = new StringWriter(); 48 | PrintWriter printer = new PrintWriter(description); 49 | this.commands.values().stream().sorted() 50 | .forEach((command) -> printer.println(describeCommand(command, maxLength + 4))); 51 | return description.toString(); 52 | } 53 | 54 | private String describeCommand(Command command, int length) { 55 | return " " + rightPad(command.getName(), length) + command.getDescription(); 56 | } 57 | 58 | private static String rightPad(String input, int length) { 59 | StringBuffer buffer = new StringBuffer(input); 60 | while (buffer.length() < length) { 61 | buffer.append(" "); 62 | } 63 | return buffer.toString(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/UserHomeBomrPropertiesEnvironmentPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.util.Properties; 23 | 24 | import org.apache.commons.logging.Log; 25 | import org.apache.commons.logging.LogFactory; 26 | 27 | import org.springframework.boot.SpringApplication; 28 | import org.springframework.boot.env.EnvironmentPostProcessor; 29 | import org.springframework.core.env.ConfigurableEnvironment; 30 | import org.springframework.core.env.PropertiesPropertySource; 31 | 32 | /** 33 | * {@link EnvironmentPostProcessor} that loads a {@code .bomr.properties} file from the 34 | * user's home directory. 35 | * 36 | * @author Andy Wilkinson 37 | */ 38 | final class UserHomeBomrPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor { 39 | 40 | private Log logger = LogFactory.getLog(UserHomeBomrPropertiesEnvironmentPostProcessor.class); 41 | 42 | @Override 43 | public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { 44 | File bomrPropertiesFile = new File(System.getProperty("user.home"), ".bomr.properties"); 45 | if (bomrPropertiesFile.exists()) { 46 | Properties bomrProperties = new Properties(); 47 | try (FileReader reader = new FileReader(bomrPropertiesFile)) { 48 | bomrProperties.load(reader); 49 | } 50 | catch (IOException ex) { 51 | this.logger.warn("Failed to load '" + bomrPropertiesFile.getAbsolutePath() + "'", ex); 52 | } 53 | environment.getPropertySources().addLast(new PropertiesPropertySource("bomr", bomrProperties)); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.util.Set; 20 | 21 | import io.spring.bomr.Command; 22 | 23 | import org.springframework.util.StringUtils; 24 | 25 | /** 26 | * A command to list all of the artifacts that are available with a particular group id 27 | * and version. 28 | * 29 | * @author Andy Wilkinson 30 | */ 31 | class ArtifactsCommand implements Command { 32 | 33 | @Override 34 | public String getName() { 35 | return "artifacts"; 36 | } 37 | 38 | @Override 39 | public String getDescription() { 40 | return "Lists the artifacts in a group with a matching version"; 41 | } 42 | 43 | @Override 44 | public void invoke(String[] args) { 45 | ArtifactsCommandArguments arguments = ArtifactsCommandArguments.parse(args); 46 | Set artifacts = ArtifactsFinder.forRepository(arguments.getRepository()).find(arguments.getGroup(), 47 | arguments.getVersion()); 48 | artifacts.forEach((artifact) -> { 49 | System.out.println(""); 50 | System.out.println("\t" + arguments.getGroup() + ""); 51 | System.out.println("\t" + artifact + ""); 52 | System.out.println("\t" + determineVersion(arguments) + ""); 53 | System.out.println(""); 54 | }); 55 | } 56 | 57 | private String determineVersion(ArtifactsCommandArguments arguments) { 58 | if (StringUtils.hasText(arguments.getVersionProperty())) { 59 | return "${" + arguments.getVersionProperty() + "}"; 60 | } 61 | return arguments.getVersion(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsCommandArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.io.IOException; 20 | import java.net.URI; 21 | 22 | import joptsimple.ArgumentAcceptingOptionSpec; 23 | import joptsimple.BuiltinHelpFormatter; 24 | import joptsimple.OptionParser; 25 | import joptsimple.OptionSet; 26 | 27 | /** 28 | * Command line arguments for the {@link ArtifactsCommand}. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | final class ArtifactsCommandArguments { 33 | 34 | private final String group; 35 | 36 | private final String version; 37 | 38 | private final String versionProperty; 39 | 40 | private final URI repository; 41 | 42 | private ArtifactsCommandArguments(String group, String version, String versionProperty, URI repository) { 43 | this.group = group; 44 | this.version = version; 45 | this.versionProperty = versionProperty; 46 | this.repository = (repository != null) ? repository : ArtifactsFinder.MAVEN_CENTRAL; 47 | } 48 | 49 | static ArtifactsCommandArguments parse(String[] args) { 50 | OptionParser optionParser = new OptionParser(); 51 | optionParser.formatHelpWith(new BuiltinHelpFormatter(120, 2)); 52 | ArgumentAcceptingOptionSpec versionPropertySpec = optionParser 53 | .accepts("version-property", "Version property to use in generated dependency management") 54 | .withRequiredArg().ofType(String.class); 55 | ArgumentAcceptingOptionSpec repositoryPropertySpec = optionParser 56 | .accepts("repository", "Repository to query").withRequiredArg().ofType(URI.class); 57 | try { 58 | OptionSet parsed = optionParser.parse(args); 59 | if (parsed.nonOptionArguments().size() != 2) { 60 | showUsageAndExit(optionParser); 61 | } 62 | return new ArtifactsCommandArguments((String) parsed.nonOptionArguments().get(0), 63 | (String) parsed.nonOptionArguments().get(1), parsed.valueOf(versionPropertySpec), 64 | parsed.valueOf(repositoryPropertySpec)); 65 | } 66 | catch (Exception ex) { 67 | showUsageAndExit(optionParser); 68 | } 69 | return null; 70 | } 71 | 72 | private static void showUsageAndExit(OptionParser optionParser) { 73 | System.err.println("Usage: bomr artifacts []"); 74 | System.err.println(); 75 | try { 76 | optionParser.printHelpOn(System.err); 77 | } 78 | catch (IOException ex) { 79 | // Continue 80 | } 81 | System.err.println(); 82 | System.exit(-1); 83 | } 84 | 85 | String getGroup() { 86 | return this.group; 87 | } 88 | 89 | String getVersion() { 90 | return this.version; 91 | } 92 | 93 | String getVersionProperty() { 94 | return this.versionProperty; 95 | } 96 | 97 | URI getRepository() { 98 | return this.repository; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | 22 | /** 23 | * Configuration for Bomr's artifacts support. 24 | * 25 | * @author Andy Wilkinson 26 | */ 27 | @Configuration 28 | class ArtifactsConfiguration { 29 | 30 | @Bean 31 | public ArtifactsCommand artifactsCommand() { 32 | return new ArtifactsCommand(); 33 | } 34 | 35 | @Bean 36 | public ArtifactsDeltaCommand artifactsDeltaCommand() { 37 | return new ArtifactsDeltaCommand(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsDeltaCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.util.Set; 20 | import java.util.SortedSet; 21 | import java.util.TreeSet; 22 | 23 | import io.spring.bomr.Command; 24 | 25 | import org.springframework.util.StringUtils; 26 | 27 | /** 28 | * {@link Command} to show the delta in artifacts of a particular group across two 29 | * different versions. 30 | * 31 | * @author Andy Wilkinson 32 | */ 33 | public class ArtifactsDeltaCommand implements Command { 34 | 35 | @Override 36 | public String getName() { 37 | return "artifacts-delta"; 38 | 39 | } 40 | 41 | @Override 42 | public String getDescription() { 43 | return "Lists the artifacts that have been added and removed from a " + "group across two versions"; 44 | } 45 | 46 | @Override 47 | public void invoke(String[] args) { 48 | ArtifactsDeltaCommandArguments arguments = ArtifactsDeltaCommandArguments.parse(args); 49 | ArtifactsFinder artifactsFinder = ArtifactsFinder.forRepository(arguments.getRepository()); 50 | Set oldArtifacts = artifactsFinder.find(arguments.getGroup(), arguments.getOldVersion()); 51 | Set newArtifacts = artifactsFinder.find(arguments.getGroup(), arguments.getNewVersion()); 52 | Set removedArtifacts = difference(oldArtifacts, newArtifacts); 53 | System.out.println("Removed:"); 54 | System.out.println(); 55 | if (!removedArtifacts.isEmpty()) { 56 | removedArtifacts.forEach(System.out::println); 57 | } 58 | else { 59 | System.out.println("None"); 60 | } 61 | System.out.println(); 62 | Set addedArtifacts = difference(newArtifacts, oldArtifacts); 63 | System.out.println("Added:"); 64 | System.out.println(); 65 | if (!addedArtifacts.isEmpty()) { 66 | addedArtifacts.forEach((artifact) -> { 67 | System.out.println(""); 68 | System.out.println("\t" + arguments.getGroup() + ""); 69 | System.out.println("\t" + artifact + ""); 70 | System.out.println("\t" + determineVersion(arguments) + ""); 71 | System.out.println(""); 72 | }); 73 | } 74 | else { 75 | System.out.println("None"); 76 | } 77 | } 78 | 79 | private String determineVersion(ArtifactsDeltaCommandArguments arguments) { 80 | if (StringUtils.hasText(arguments.getVersionProperty())) { 81 | return "${" + arguments.getVersionProperty() + "}"; 82 | } 83 | return arguments.getNewVersion(); 84 | } 85 | 86 | private SortedSet difference(Set one, Set two) { 87 | SortedSet result = new TreeSet<>(one); 88 | result.removeAll(two); 89 | return result; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsDeltaCommandArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.io.IOException; 20 | import java.net.URI; 21 | 22 | import joptsimple.ArgumentAcceptingOptionSpec; 23 | import joptsimple.BuiltinHelpFormatter; 24 | import joptsimple.OptionParser; 25 | import joptsimple.OptionSet; 26 | 27 | /** 28 | * Command line arguments for the {@link ArtifactsCommand}. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | final class ArtifactsDeltaCommandArguments { 33 | 34 | private final String group; 35 | 36 | private final String oldVersion; 37 | 38 | private final String newVersion; 39 | 40 | private final String versionProperty; 41 | 42 | private final URI repository; 43 | 44 | private ArtifactsDeltaCommandArguments(String group, String oldVersion, String newVersion, String versionProperty, 45 | URI repository) { 46 | this.group = group; 47 | this.oldVersion = oldVersion; 48 | this.newVersion = newVersion; 49 | this.versionProperty = versionProperty; 50 | this.repository = (repository != null) ? repository : URI.create("https://repo1.maven.org/maven2/"); 51 | } 52 | 53 | static ArtifactsDeltaCommandArguments parse(String[] args) { 54 | OptionParser optionParser = new OptionParser(); 55 | optionParser.formatHelpWith(new BuiltinHelpFormatter(120, 2)); 56 | ArgumentAcceptingOptionSpec versionPropertySpec = optionParser 57 | .accepts("version-property", "Version property to use in generated dependency management") 58 | .withRequiredArg().ofType(String.class); 59 | ArgumentAcceptingOptionSpec repositoryPropertySpec = optionParser 60 | .accepts("repository", "Repository to query").withRequiredArg().ofType(URI.class); 61 | try { 62 | OptionSet parsed = optionParser.parse(args); 63 | if (parsed.nonOptionArguments().size() != 3) { 64 | showUsageAndExit(optionParser); 65 | } 66 | return new ArtifactsDeltaCommandArguments((String) parsed.nonOptionArguments().get(0), 67 | (String) parsed.nonOptionArguments().get(1), (String) parsed.nonOptionArguments().get(2), 68 | parsed.valueOf(versionPropertySpec), parsed.valueOf(repositoryPropertySpec)); 69 | } 70 | catch (Exception ex) { 71 | showUsageAndExit(optionParser); 72 | } 73 | return null; 74 | } 75 | 76 | private static void showUsageAndExit(OptionParser optionParser) { 77 | System.err.println("Usage: bomr artifacts-delta []"); 78 | System.err.println(); 79 | try { 80 | optionParser.printHelpOn(System.err); 81 | } 82 | catch (IOException ex) { 83 | // Continue 84 | } 85 | System.err.println(); 86 | System.exit(-1); 87 | } 88 | 89 | String getGroup() { 90 | return this.group; 91 | } 92 | 93 | String getOldVersion() { 94 | return this.oldVersion; 95 | } 96 | 97 | String getNewVersion() { 98 | return this.newVersion; 99 | } 100 | 101 | String getVersionProperty() { 102 | return this.versionProperty; 103 | } 104 | 105 | URI getRepository() { 106 | return this.repository; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/ArtifactsFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.net.URI; 20 | import java.util.Set; 21 | 22 | import org.springframework.web.client.RestTemplate; 23 | 24 | /** 25 | * An {@code ArtifactsFinder} is used to find artifacts in a repository. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | interface ArtifactsFinder { 30 | 31 | URI MAVEN_CENTRAL = URI.create("https://repo1.maven.org/maven2/"); 32 | 33 | static ArtifactsFinder forRepository(URI repository) { 34 | return repository.equals(MAVEN_CENTRAL) ? new MavenCentralSearchArtifactsFinder(new RestTemplate()) 35 | : new MavenRepositoryArtifactsFinder(new RestTemplate(), repository); 36 | } 37 | 38 | /** 39 | * Finds the artifacts with the given {@code group} and {@code version} in the 40 | * repository. 41 | * @param group the group 42 | * @param version the version 43 | * @return the artifacts in the group with the required version 44 | */ 45 | Set find(String group, String version); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/MavenCentralSearchArtifactsFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Set; 22 | import java.util.TreeSet; 23 | 24 | import com.jayway.jsonpath.DocumentContext; 25 | import com.jayway.jsonpath.JsonPath; 26 | 27 | import org.springframework.web.client.RestOperations; 28 | 29 | /** 30 | * An {@link ArtifactsFinder} for Maven Central. Finds artifacts by querying Maven Central 31 | * Search. 32 | * 33 | * @author Andy Wilkinson 34 | */ 35 | class MavenCentralSearchArtifactsFinder implements ArtifactsFinder { 36 | 37 | private static final int PAGE_SIZE = 20; 38 | 39 | private static final String URI_TEMPLATE = "https://search.maven.org/solrsearch/select?q=g:{group}+AND+v:{version}&rows={pageSize}&start={start}"; 40 | 41 | private final RestOperations rest; 42 | 43 | MavenCentralSearchArtifactsFinder(RestOperations rest) { 44 | this.rest = rest; 45 | } 46 | 47 | @Override 48 | public Set find(String group, String version) { 49 | List artifacts = new ArrayList<>(); 50 | int total; 51 | int start = 0; 52 | do { 53 | String result = this.rest.getForObject(URI_TEMPLATE, String.class, group, version, PAGE_SIZE, start); 54 | DocumentContext json = JsonPath.parse(result); 55 | artifacts.addAll(json.read("$.response.docs.[?('.jar' in @.ec)].a")); 56 | total = json.read("$.response.numFound"); 57 | start += PAGE_SIZE; 58 | } 59 | while (start < total); 60 | return new TreeSet(artifacts); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/artifacts/MavenRepositoryArtifactsFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.net.URI; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Set; 23 | import java.util.TreeSet; 24 | import java.util.regex.Matcher; 25 | import java.util.regex.Pattern; 26 | 27 | import org.springframework.http.ResponseEntity; 28 | import org.springframework.web.client.RestClientException; 29 | import org.springframework.web.client.RestOperations; 30 | 31 | /** 32 | * Finds artifacts in a group with a particular version that are available in a Maven 33 | * repository. 34 | * 35 | * @author Andy Wilkinson 36 | */ 37 | class MavenRepositoryArtifactsFinder implements ArtifactsFinder { 38 | 39 | private final Pattern linkPattern = Pattern.compile(".*/"); 40 | 41 | private final RestOperations rest; 42 | 43 | private final URI repository; 44 | 45 | MavenRepositoryArtifactsFinder(RestOperations rest, URI repository) { 46 | this.rest = rest; 47 | this.repository = repository; 48 | } 49 | 50 | @Override 51 | public Set find(String group, String version) { 52 | URI groupUri = this.repository.resolve(group.replace('.', '/') + "/"); 53 | List artifactLinks = extractLinks(groupUri); 54 | Set artifacts = new TreeSet<>(); 55 | for (String artifactLink : artifactLinks) { 56 | List versionLinks = extractLinks(groupUri.resolve(artifactLink)); 57 | if (versionLinks.contains(version + "/")) { 58 | String artifact = artifactLink.substring(0, artifactLink.length() - 1); 59 | if (jarArtifactExists(group, artifact, version)) { 60 | artifacts.add(artifact); 61 | } 62 | } 63 | } 64 | return artifacts; 65 | } 66 | 67 | private List extractLinks(URI uri) { 68 | try { 69 | ResponseEntity response = this.rest.getForEntity(uri, String.class); 70 | String body = response.getBody(); 71 | List links = new ArrayList(); 72 | Matcher matcher = this.linkPattern.matcher(body); 73 | while (matcher.find()) { 74 | String candidate = matcher.group(1); 75 | if (!"../".equals(candidate)) { 76 | links.add(candidate); 77 | } 78 | } 79 | return links; 80 | } 81 | catch (RestClientException ex) { 82 | System.err.println(uri + " " + ex.getMessage()); 83 | System.exit(-1); 84 | return null; 85 | } 86 | } 87 | 88 | private boolean jarArtifactExists(String group, String artifact, String version) { 89 | String jarUrl = this.repository + group.replace('.', '/') + "/" + artifact + "/" + version + "/" + artifact 90 | + "-" + version + ".jar"; 91 | try { 92 | this.rest.headForHeaders(jarUrl); 93 | return true; 94 | } 95 | catch (RestClientException ex) { 96 | return false; 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/GitHub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | /** 20 | * Minimal API for interacting with GitHub. 21 | * 22 | * @author Andy Wilkinson 23 | */ 24 | public interface GitHub { 25 | 26 | /** 27 | * Returns a {@link GitHubRepository} with the given {@code name} in the given 28 | * {@code organization}. 29 | * @param organization the organization 30 | * @param name the name of the repository 31 | * @return the repository 32 | */ 33 | GitHubRepository getRepository(String organization, String name); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/GitHubConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | 23 | /** 24 | * {@link Configuration} for GitHub-related components. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | @Configuration 29 | @EnableConfigurationProperties(GitHubProperties.class) 30 | class GitHubConfiguration { 31 | 32 | @Bean 33 | public GitHub gitHub(GitHubProperties gitHubProperties) { 34 | return new StandardGitHub(gitHubProperties.getUsername(), gitHubProperties.getPassword()); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/GitHubProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | import org.springframework.boot.context.properties.ConfigurationProperties; 20 | 21 | /** 22 | * Properties for configuring access to GitHub. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | @ConfigurationProperties("bomr.github") 27 | class GitHubProperties { 28 | 29 | /** 30 | * Username for authentication with GitHub. 31 | */ 32 | private String username; 33 | 34 | /** 35 | * Password for authentication with GitHub. 36 | */ 37 | private String password; 38 | 39 | /** 40 | * Returns the username used to authenticate with GitHub. 41 | * @return the username 42 | */ 43 | public String getUsername() { 44 | return this.username; 45 | } 46 | 47 | /** 48 | * Sets the username used to authenticate with GitHub. 49 | * @param username the username 50 | */ 51 | public void setUsername(String username) { 52 | this.username = username; 53 | } 54 | 55 | /** 56 | * Returns the password used to authenticate with GitHub. 57 | * @return the passwrd 58 | */ 59 | public String getPassword() { 60 | return this.password; 61 | } 62 | 63 | /** 64 | * Sets the password used to authenticate with GitHub. 65 | * @param password the password 66 | */ 67 | public void setPassword(String password) { 68 | this.password = password; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/GitHubRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * Minimal API for interacting with a GitHub repository. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | public interface GitHubRepository { 27 | 28 | /** 29 | * Opens a new issue with the given title. The given {@code labels} will be applied to 30 | * the issue and it will be assigned to the given {@code milestone}. 31 | * @param title the title of the issue 32 | * @param labels the labels to apply to the issue 33 | * @param milestone the milestone to assign the issue to 34 | * @return the number of the new issue 35 | */ 36 | int openIssue(String title, List labels, Milestone milestone); 37 | 38 | /** 39 | * Returns the labels in the repository. 40 | * @return the labels 41 | */ 42 | List getLabels(); 43 | 44 | /** 45 | * Returns the milestones in the repository. 46 | * @return the milestones 47 | */ 48 | List getMilestones(); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/Milestone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | /** 20 | * A milestone in a {@link GitHubRepository GitHub repository}. 21 | * 22 | * @author Andy Wilkinson 23 | */ 24 | public class Milestone { 25 | 26 | private final String name; 27 | 28 | private final int number; 29 | 30 | Milestone(String name, int number) { 31 | this.name = name; 32 | this.number = number; 33 | } 34 | 35 | /** 36 | * Returns the name of the milestone. 37 | * @return the name 38 | */ 39 | public String getName() { 40 | return this.name; 41 | } 42 | 43 | /** 44 | * Returns the number of the milestone. 45 | * @return the number 46 | */ 47 | public int getNumber() { 48 | return this.number; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return this.name + " (" + this.number + ")"; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/StandardGitHub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | import java.io.IOException; 20 | import java.util.Base64; 21 | 22 | import org.springframework.http.HttpRequest; 23 | import org.springframework.http.MediaType; 24 | import org.springframework.http.client.ClientHttpRequestExecution; 25 | import org.springframework.http.client.ClientHttpRequestInterceptor; 26 | import org.springframework.http.client.ClientHttpResponse; 27 | import org.springframework.web.client.RestTemplate; 28 | import org.springframework.web.util.DefaultUriBuilderFactory; 29 | import org.springframework.web.util.UriTemplateHandler; 30 | 31 | /** 32 | * Standard implementation of {@link GitHub}. 33 | * 34 | * @author Andy Wilkinson 35 | */ 36 | final class StandardGitHub implements GitHub { 37 | 38 | private final String username; 39 | 40 | private final String password; 41 | 42 | StandardGitHub(String username, String password) { 43 | this.username = username; 44 | this.password = password; 45 | } 46 | 47 | @Override 48 | public GitHubRepository getRepository(String organization, String name) { 49 | RestTemplate restTemplate = new RestTemplate(); 50 | restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() { 51 | 52 | @Override 53 | public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 54 | throws IOException { 55 | request.getHeaders().add("User-Agent", StandardGitHub.this.username); 56 | request.getHeaders().add("Authorization", "Basic " + Base64.getEncoder().encodeToString( 57 | (StandardGitHub.this.username + ":" + StandardGitHub.this.password).getBytes())); 58 | request.getHeaders().add("Accept", MediaType.APPLICATION_JSON_VALUE); 59 | return execution.execute(request, body); 60 | } 61 | 62 | }); 63 | UriTemplateHandler uriTemplateHandler = new DefaultUriBuilderFactory( 64 | "https://api.github.com/repos/" + organization + "/" + name + "/"); 65 | restTemplate.setUriTemplateHandler(uriTemplateHandler); 66 | return new StandardGitHubRepository(restTemplate); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/github/StandardGitHubRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.github; 18 | 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.function.Function; 23 | import java.util.stream.Collectors; 24 | 25 | import org.springframework.http.ResponseEntity; 26 | import org.springframework.web.client.RestTemplate; 27 | 28 | /** 29 | * Standard implementation of {@link GitHubRepository}. 30 | * 31 | * @author Andy Wilkinson 32 | */ 33 | final class StandardGitHubRepository implements GitHubRepository { 34 | 35 | private final RestTemplate rest; 36 | 37 | StandardGitHubRepository(RestTemplate restTemplate) { 38 | this.rest = restTemplate; 39 | } 40 | 41 | @Override 42 | @SuppressWarnings("rawtypes") 43 | public int openIssue(String title, List labels, Milestone milestone) { 44 | Map body = new HashMap<>(); 45 | body.put("title", title); 46 | if (milestone != null) { 47 | body.put("milestone", milestone.getNumber()); 48 | } 49 | if (!labels.isEmpty()) { 50 | body.put("labels", labels); 51 | } 52 | ResponseEntity response = this.rest.postForEntity("issues", body, Map.class); 53 | return (Integer) response.getBody().get("number"); 54 | } 55 | 56 | @Override 57 | public List getLabels() { 58 | return get("labels?per_page=100", (label) -> (String) label.get("name")); 59 | } 60 | 61 | @Override 62 | public List getMilestones() { 63 | return get("milestones?per_page=100", 64 | (milestone) -> new Milestone((String) milestone.get("title"), (Integer) milestone.get("number"))); 65 | } 66 | 67 | @SuppressWarnings({ "rawtypes", "unchecked" }) 68 | private List get(String name, Function, T> mapper) { 69 | ResponseEntity response = this.rest.getForEntity(name, List.class); 70 | List> body = response.getBody(); 71 | return body.stream().map(mapper).collect(Collectors.toList()); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/Bom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.FileWriter; 22 | import java.io.IOException; 23 | import java.util.Collections; 24 | import java.util.LinkedHashMap; 25 | import java.util.Map; 26 | 27 | import javax.xml.parsers.DocumentBuilder; 28 | import javax.xml.parsers.DocumentBuilderFactory; 29 | import javax.xml.xpath.XPath; 30 | import javax.xml.xpath.XPathConstants; 31 | import javax.xml.xpath.XPathExpressionException; 32 | import javax.xml.xpath.XPathFactory; 33 | 34 | import io.spring.bomr.upgrade.BomVersions.BomVersion; 35 | import org.w3c.dom.Document; 36 | import org.w3c.dom.Node; 37 | import org.w3c.dom.NodeList; 38 | 39 | import org.springframework.util.FileCopyUtils; 40 | 41 | /** 42 | * A Maven bom. 43 | * 44 | * @author Andy Wilkinson 45 | */ 46 | final class Bom { 47 | 48 | private final File bomFile; 49 | 50 | private final Map managedProjects; 51 | 52 | Bom(File bomFile) { 53 | this.bomFile = bomFile; 54 | Document bom = parseBom(bomFile); 55 | this.managedProjects = extractManagedProjects(bom, new BomVersions(bom)); 56 | } 57 | 58 | private Document parseBom(File bomFile) { 59 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 60 | try { 61 | DocumentBuilder builder = factory.newDocumentBuilder(); 62 | return builder.parse(bomFile); 63 | } 64 | catch (Exception ex) { 65 | throw new RuntimeException(ex); 66 | } 67 | } 68 | 69 | private Map extractManagedProjects(Document bom, BomVersions versions) { 70 | Map projects = new LinkedHashMap<>(); 71 | try { 72 | collectProjects("/project/dependencyManagement/dependencies/dependency", projects, bom, versions); 73 | collectProjects("/project/build/pluginManagement/plugins/plugin", projects, bom, versions); 74 | } 75 | catch (Exception ex) { 76 | throw new RuntimeException(ex); 77 | } 78 | return projects; 79 | } 80 | 81 | private void collectProjects(String managedExpression, Map projects, Document bom, 82 | BomVersions versions) throws XPathExpressionException { 83 | XPath xpath = XPathFactory.newInstance().newXPath(); 84 | String projectGroupId = xpath.evaluate("/project/groupId/text()", bom); 85 | NodeList managedDependencies = (NodeList) xpath.evaluate(managedExpression, bom, XPathConstants.NODESET); 86 | for (int i = 0; i < managedDependencies.getLength(); i++) { 87 | Node managedDependency = managedDependencies.item(i); 88 | String groupId = xpath.evaluate("groupId/text()", managedDependency); 89 | if (!groupId.equals(projectGroupId)) { 90 | BomVersion version = versions.resolve(xpath.evaluate("version/text()", managedDependency)); 91 | if (version != null) { 92 | Project project = projects.computeIfAbsent(new ProjectName(version), 93 | (projectName) -> new Project(projectName, version)); 94 | String artifactId = xpath.evaluate("artifactId/text()", managedDependency); 95 | project.getModules().add(new Module(groupId, artifactId)); 96 | } 97 | } 98 | } 99 | 100 | } 101 | 102 | Map getManagedProjects() { 103 | return Collections.unmodifiableMap(this.managedProjects); 104 | } 105 | 106 | void applyUpgrade(Upgrade upgrade) { 107 | String versionProperty = upgrade.getProject().getVersion().getProperty(); 108 | try { 109 | String updatedBom = FileCopyUtils.copyToString(new FileReader(this.bomFile)).replaceAll( 110 | "<" + versionProperty + ">.*", 111 | "<" + versionProperty + ">" + upgrade.getVersion() + ""); 112 | FileCopyUtils.copy(updatedBom, new FileWriter(this.bomFile)); 113 | } 114 | catch (IOException ex) { 115 | throw new RuntimeException(ex); 116 | } 117 | } 118 | 119 | void commit(String message) { 120 | try { 121 | if (new ProcessBuilder().command("git", "add", this.bomFile.getAbsolutePath()).start().waitFor() != 0) { 122 | throw new IllegalStateException("git add failed"); 123 | } 124 | if (new ProcessBuilder().command("git", "commit", "-m", message).start().waitFor() != 0) { 125 | throw new IllegalStateException("git commit failed"); 126 | } 127 | } 128 | catch (InterruptedException ex) { 129 | Thread.currentThread().interrupt(); 130 | } 131 | catch (IOException ex) { 132 | throw new RuntimeException(ex); 133 | } 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/BomUpgrader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.File; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Optional; 23 | 24 | import io.spring.bomr.github.GitHub; 25 | import io.spring.bomr.github.GitHubRepository; 26 | import io.spring.bomr.github.Milestone; 27 | 28 | /** 29 | * Handles the process of upgrading the versions of the dependencies managed by a bom. 30 | * 31 | * @author Andy Wilkinson 32 | */ 33 | final class BomUpgrader { 34 | 35 | private final GitHub gitHub; 36 | 37 | private final VersionResolver versionResolver; 38 | 39 | private final UpgradePolicy upgradePolicy; 40 | 41 | private final List prohibitedVersions; 42 | 43 | BomUpgrader(GitHub gitHub, VersionResolver versionResolver, UpgradePolicy upgradePolicy, 44 | List prohibitedVersions) { 45 | this.gitHub = gitHub; 46 | this.versionResolver = versionResolver; 47 | this.upgradePolicy = upgradePolicy; 48 | this.prohibitedVersions = prohibitedVersions; 49 | } 50 | 51 | void upgrade(File bomFile, String organization, String repositoryName, List labels, String milestoneName) { 52 | GitHubRepository repository = this.gitHub.getRepository(organization, repositoryName); 53 | List availableLabels = repository.getLabels(); 54 | if (!availableLabels.containsAll(labels)) { 55 | List unknownLabels = new ArrayList<>(labels); 56 | unknownLabels.removeAll(availableLabels); 57 | unknownLabels.forEach((label) -> System.err.println("Unknown label '" + label + "'")); 58 | System.exit(1); 59 | } 60 | Milestone milestone = determineMilestone(repository, milestoneName); 61 | Bom bom = new Bom(bomFile); 62 | List upgrades = new InteractiveUpgradeResolver(this.versionResolver, this.upgradePolicy, 63 | this.prohibitedVersions).resolveUpgrades(bom.getManagedProjects().values()); 64 | upgrades.forEach((upgrade) -> applyUpgrade(upgrade, bom, repository, labels, milestone)); 65 | } 66 | 67 | private Milestone determineMilestone(GitHubRepository repository, String milestoneName) { 68 | if (milestoneName == null) { 69 | return null; 70 | } 71 | List milestones = repository.getMilestones(); 72 | Optional matchingMilestone = milestones.stream() 73 | .filter((milestone) -> milestone.getName().equals(milestoneName)).findFirst(); 74 | if (!matchingMilestone.isPresent()) { 75 | System.err.println("Unknown milestone '" + milestoneName + "'"); 76 | System.exit(1); 77 | } 78 | return matchingMilestone.get(); 79 | } 80 | 81 | private void applyUpgrade(Upgrade upgrade, Bom bom, GitHubRepository repository, List labels, 82 | Milestone milestone) { 83 | String description = "Upgrade to " + upgrade.getProject().getName() + " " + upgrade.getVersion(); 84 | int issueNumber = repository.openIssue(description, labels, milestone); 85 | bom.applyUpgrade(upgrade); 86 | bom.commit(description + "\n\nCloses gh-" + issueNumber); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/BomVersions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import javax.xml.xpath.XPathConstants; 23 | import javax.xml.xpath.XPathFactory; 24 | 25 | import io.spring.bomr.upgrade.version.DependencyVersion; 26 | import org.w3c.dom.Document; 27 | import org.w3c.dom.Node; 28 | import org.w3c.dom.NodeList; 29 | 30 | /** 31 | * The versions declared in the <properties> section of a bom. 32 | * 33 | * @author Andy Wilkinson 34 | */ 35 | final class BomVersions { 36 | 37 | private Map versions = new HashMap<>(); 38 | 39 | BomVersions(Document bom) { 40 | try { 41 | NodeList propertyNodes = (NodeList) XPathFactory.newInstance().newXPath().evaluate("/project/properties/*", 42 | bom, XPathConstants.NODESET); 43 | for (int i = 0; i < propertyNodes.getLength(); i++) { 44 | Node propertyNode = propertyNodes.item(i); 45 | this.versions.put(propertyNode.getNodeName(), propertyNode.getTextContent()); 46 | } 47 | } 48 | catch (Exception ex) { 49 | throw new RuntimeException(ex); 50 | } 51 | } 52 | 53 | BomVersion resolve(String requested) { 54 | String property = requested; 55 | String value = requested; 56 | while (value != null && value.startsWith("${") && value.endsWith("}")) { 57 | property = value.substring(2, value.length() - 1); 58 | value = this.versions.get(property); 59 | } 60 | if (value == null) { 61 | return null; 62 | } 63 | return new BomVersion(property, DependencyVersion.parse(value)); 64 | } 65 | 66 | /** 67 | * An individual version extracted from the <properties> section of 68 | * a bom. 69 | */ 70 | static class BomVersion { 71 | 72 | private final String property; 73 | 74 | private final DependencyVersion version; 75 | 76 | BomVersion(String property, DependencyVersion version) { 77 | this.property = property; 78 | this.version = version; 79 | } 80 | 81 | String getProperty() { 82 | return this.property; 83 | } 84 | 85 | DependencyVersion getVersion() { 86 | return this.version; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return this.property + ":" + this.version; 92 | } 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/InteractiveUpgradeResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collection; 21 | import java.util.LinkedHashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.SortedSet; 25 | import java.util.function.BiConsumer; 26 | import java.util.function.Function; 27 | import java.util.stream.Collectors; 28 | 29 | import io.spring.bomr.upgrade.BomVersions.BomVersion; 30 | import io.spring.bomr.upgrade.version.DependencyVersion; 31 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 32 | import org.apache.maven.artifact.versioning.VersionRange; 33 | 34 | import org.springframework.util.StringUtils; 35 | 36 | /** 37 | * Interactive {@link UpgradeResolver} that uses command line input to choose the upgrades 38 | * to apply. 39 | * 40 | * @author Andy Wilkinson 41 | */ 42 | final class InteractiveUpgradeResolver implements UpgradeResolver { 43 | 44 | private final VersionResolver versionResolver; 45 | 46 | private final UpgradePolicy upgradePolicy; 47 | 48 | private final Map prohibitedVersions; 49 | 50 | InteractiveUpgradeResolver(VersionResolver versionResolver, UpgradePolicy upgradePolicy, 51 | List prohibitedVersions) { 52 | this.versionResolver = versionResolver; 53 | this.upgradePolicy = upgradePolicy; 54 | this.prohibitedVersions = prohibitedVersions.stream() 55 | .collect(Collectors.toMap(ProhibitedVersions::getProject, Function.identity())); 56 | } 57 | 58 | @Override 59 | public List resolveUpgrades(Collection projects) { 60 | return projects.stream().map(this::resolveUpgrade).filter((upgrade) -> upgrade != null) 61 | .collect(Collectors.toList()); 62 | } 63 | 64 | private Upgrade resolveUpgrade(Project project) { 65 | Map> moduleVersions = new LinkedHashMap<>(); 66 | ProhibitedVersions prohibitedVersions = this.prohibitedVersions.get(project.getName().getRawName()); 67 | project.getModules().forEach((module) -> moduleVersions.put(module.getArtifactId(), 68 | getLaterVersionsForModule(module, project.getVersion()))); 69 | List allVersions = moduleVersions.values().stream().flatMap(SortedSet::stream).distinct() 70 | .filter((dependencyVersion) -> isPermitted(dependencyVersion, prohibitedVersions)) 71 | .collect(Collectors.toList()); 72 | if (allVersions.isEmpty()) { 73 | return null; 74 | } 75 | System.out.println(); 76 | System.out.println(project.getName() + " " + project.getVersion().getVersion()); 77 | System.out.println(); 78 | forEachWithIndex(allVersions, (index, version) -> { 79 | List missingModules = getMissingModules(moduleVersions, version); 80 | System.out.print(" " + (index + 1) + ". " + version); 81 | if (!missingModules.isEmpty()) { 82 | System.out.print(" (Some modules are missing: " 83 | + StringUtils.collectionToDelimitedString(missingModules, ", ") + ")"); 84 | } 85 | System.out.println(); 86 | }); 87 | System.out.println(); 88 | String read = System.console().readLine("Please select a version: "); 89 | if (!StringUtils.hasText(read)) { 90 | return null; 91 | } 92 | int selection = Integer.parseInt(read); 93 | return new Upgrade(project, allVersions.get(selection - 1)); 94 | } 95 | 96 | private boolean isPermitted(DependencyVersion dependencyVersion, ProhibitedVersions prohibitedVersions) { 97 | if (prohibitedVersions == null) { 98 | return true; 99 | } 100 | for (VersionRange range : prohibitedVersions.getVersions()) { 101 | if (range.containsVersion(new DefaultArtifactVersion(dependencyVersion.toString()))) { 102 | return false; 103 | } 104 | } 105 | return true; 106 | } 107 | 108 | private List getMissingModules(Map> moduleVersions, 109 | DependencyVersion version) { 110 | List missingModules = new ArrayList<>(); 111 | moduleVersions.forEach((name, versions) -> { 112 | if (!versions.contains(version)) { 113 | missingModules.add(name); 114 | } 115 | }); 116 | return missingModules; 117 | } 118 | 119 | private SortedSet getLaterVersionsForModule(Module module, BomVersion currentVersion) { 120 | SortedSet versions = this.versionResolver.resolveVersions(module); 121 | versions.removeIf((candidate) -> !this.upgradePolicy.test(candidate, currentVersion.getVersion())); 122 | return versions; 123 | } 124 | 125 | private void forEachWithIndex(Collection collection, BiConsumer consumer) { 126 | int i = 0; 127 | for (T item : collection) { 128 | consumer.accept(i++, item); 129 | } 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/MavenMetadataVersionResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.StringReader; 20 | import java.util.HashSet; 21 | import java.util.List; 22 | import java.util.Set; 23 | import java.util.SortedSet; 24 | import java.util.TreeSet; 25 | import java.util.stream.Collectors; 26 | 27 | import javax.xml.parsers.DocumentBuilderFactory; 28 | import javax.xml.xpath.XPathConstants; 29 | import javax.xml.xpath.XPathFactory; 30 | 31 | import io.spring.bomr.upgrade.version.DependencyVersion; 32 | import org.w3c.dom.Document; 33 | import org.w3c.dom.NodeList; 34 | import org.xml.sax.InputSource; 35 | 36 | import org.springframework.http.HttpStatus; 37 | import org.springframework.web.client.HttpClientErrorException; 38 | import org.springframework.web.client.RestTemplate; 39 | 40 | /** 41 | * A {@link VersionResolver} that examines {@code maven-metadata.xml} to determine the 42 | * available versions. 43 | * 44 | * @author Andy Wilkinson 45 | */ 46 | final class MavenMetadataVersionResolver implements VersionResolver { 47 | 48 | private final RestTemplate rest; 49 | 50 | private final List repositoryUrls; 51 | 52 | MavenMetadataVersionResolver(List repositoryUrls) { 53 | this(new RestTemplate(), repositoryUrls); 54 | } 55 | 56 | MavenMetadataVersionResolver(RestTemplate restTemplate, List repositoryUrls) { 57 | this.rest = restTemplate; 58 | this.repositoryUrls = repositoryUrls; 59 | } 60 | 61 | @Override 62 | public SortedSet resolveVersions(Module module) { 63 | Set versions = new HashSet(); 64 | for (String repositoryUrl : this.repositoryUrls) { 65 | versions.addAll(resolveVersions(module, repositoryUrl)); 66 | } 67 | return new TreeSet<>(versions.stream().map(DependencyVersion::parse).collect(Collectors.toSet())); 68 | } 69 | 70 | private Set resolveVersions(Module module, String repositoryUrl) { 71 | Set versions = new HashSet(); 72 | String url = repositoryUrl + "/" + module.getGroupId().replace('.', '/') + "/" + module.getArtifactId() 73 | + "/maven-metadata.xml"; 74 | try { 75 | String metadata = this.rest.getForObject(url, String.class); 76 | Document metadataDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder() 77 | .parse(new InputSource(new StringReader(metadata))); 78 | NodeList versionNodes = (NodeList) XPathFactory.newInstance().newXPath() 79 | .evaluate("/metadata/versioning/versions/version", metadataDocument, XPathConstants.NODESET); 80 | for (int i = 0; i < versionNodes.getLength(); i++) { 81 | versions.add(versionNodes.item(i).getTextContent()); 82 | } 83 | } 84 | catch (HttpClientErrorException ex) { 85 | if (ex.getStatusCode() != HttpStatus.NOT_FOUND) { 86 | System.err.println("Failed to download maven-metadata.xml for " + module + " from " + url + ": " 87 | + ex.getMessage()); 88 | } 89 | } 90 | catch (Exception ex) { 91 | System.err.println("Failed to resolve versions for module " + module + " in repository " + repositoryUrl 92 | + ": " + ex.getMessage()); 93 | } 94 | return versions; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/Module.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | /** 20 | * A module of a {@link Project}. 21 | * 22 | * @author Andy Wilkinson 23 | */ 24 | final class Module { 25 | 26 | private final String groupId; 27 | 28 | private final String artifactId; 29 | 30 | Module(String groupId, String artifactId) { 31 | this.groupId = groupId; 32 | this.artifactId = artifactId; 33 | } 34 | 35 | String getGroupId() { 36 | return this.groupId; 37 | } 38 | 39 | String getArtifactId() { 40 | return this.artifactId; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return this.groupId + ":" + this.artifactId; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/ProhibitedVersions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.List; 20 | 21 | import org.apache.maven.artifact.versioning.VersionRange; 22 | 23 | /** 24 | * Prohibited versions of a project. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | class ProhibitedVersions { 29 | 30 | private String project; 31 | 32 | private List versions; 33 | 34 | public String getProject() { 35 | return this.project; 36 | } 37 | 38 | public void setProject(String project) { 39 | this.project = project; 40 | } 41 | 42 | public List getVersions() { 43 | return this.versions; 44 | } 45 | 46 | public void setVersions(List versions) { 47 | this.versions = versions; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/Project.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import io.spring.bomr.upgrade.BomVersions.BomVersion; 23 | 24 | /** 25 | * A project made up of one or more {@link Module Modules}. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | final class Project { 30 | 31 | private final ProjectName name; 32 | 33 | private final BomVersion version; 34 | 35 | private final List modules = new ArrayList<>(); 36 | 37 | Project(ProjectName name, BomVersion version) { 38 | this.name = name; 39 | this.version = version; 40 | } 41 | 42 | ProjectName getName() { 43 | return this.name; 44 | } 45 | 46 | BomVersion getVersion() { 47 | return this.version; 48 | } 49 | 50 | List getModules() { 51 | return this.modules; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/ProjectName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import io.spring.bomr.upgrade.BomVersions.BomVersion; 20 | 21 | /** 22 | * The name of a {@link Project}. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | final class ProjectName { 27 | 28 | private final String name; 29 | 30 | private final String rawName; 31 | 32 | ProjectName(BomVersion version) { 33 | StringBuilder nameBuilder = new StringBuilder(); 34 | String name = version.getProperty(); 35 | if (name.endsWith(".version")) { 36 | name = name.substring(0, name.length() - ".version".length()); 37 | } 38 | this.rawName = name; 39 | for (int i = 0; i < name.length(); i++) { 40 | char c = name.charAt(i); 41 | if (i == 0 || name.charAt(i - 1) == '-') { 42 | c = Character.toUpperCase(c); 43 | } 44 | if (c == '-') { 45 | c = ' '; 46 | } 47 | nameBuilder.append(c); 48 | } 49 | this.name = nameBuilder.toString(); 50 | } 51 | 52 | String getRawName() { 53 | return this.rawName; 54 | } 55 | 56 | @Override 57 | public boolean equals(Object obj) { 58 | if (this == obj) { 59 | return true; 60 | } 61 | if (obj == null) { 62 | return false; 63 | } 64 | if (getClass() != obj.getClass()) { 65 | return false; 66 | } 67 | ProjectName other = (ProjectName) obj; 68 | return this.name.equals(other.name); 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | return this.name.hashCode(); 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return this.name; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/StringToVersionRangeConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 20 | import org.apache.maven.artifact.versioning.VersionRange; 21 | 22 | import org.springframework.core.convert.converter.Converter; 23 | 24 | /** 25 | * {@link Converter} to create a {@link VersionRange} from a {@link String}. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | class StringToVersionRangeConverter implements Converter { 30 | 31 | @Override 32 | public VersionRange convert(String source) { 33 | try { 34 | return VersionRange.createFromVersionSpec(source); 35 | } 36 | catch (InvalidVersionSpecificationException ex) { 37 | throw new IllegalArgumentException(ex); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/Upgrade.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import io.spring.bomr.upgrade.version.DependencyVersion; 20 | import org.eclipse.aether.version.Version; 21 | 22 | /** 23 | * An upgrade to change a {@link Project} to use a new {@link Version}. 24 | * 25 | * @author Andy Wilkinson 26 | */ 27 | final class Upgrade { 28 | 29 | private final Project project; 30 | 31 | private final DependencyVersion version; 32 | 33 | Upgrade(Project project, DependencyVersion version) { 34 | this.project = project; 35 | this.version = version; 36 | } 37 | 38 | Project getProject() { 39 | return this.project; 40 | } 41 | 42 | DependencyVersion getVersion() { 43 | return this.version; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradeCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.File; 20 | import java.util.Arrays; 21 | 22 | import io.spring.bomr.Command; 23 | import io.spring.bomr.github.GitHub; 24 | 25 | /** 26 | * A {@link Command} for upgrading the versions of the plugins and dependencies managed by 27 | * a bom. 28 | * 29 | * @author Andy Wilkinson 30 | */ 31 | final class UpgradeCommand implements Command { 32 | 33 | private final GitHub gitHub; 34 | 35 | private final UpgradeProperties properties; 36 | 37 | private final File bom; 38 | 39 | UpgradeCommand(GitHub gitHub, UpgradeProperties upgradeProperties, File bom) { 40 | this.gitHub = gitHub; 41 | this.properties = upgradeProperties; 42 | this.bom = bom; 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return "upgrade"; 48 | } 49 | 50 | @Override 51 | public String getDescription() { 52 | return "Upgrades the versions of the plugins and dependencies managed by a bom"; 53 | } 54 | 55 | @Override 56 | public void invoke(String[] args) { 57 | UpgradeCommandArguments arguments = UpgradeCommandArguments.parse(args); 58 | if (this.bom == null) { 59 | System.err.println(); 60 | System.err.println("Fatal: bomr.bom has not been configured"); 61 | System.err.println(); 62 | System.err.println("Check your configuration in .bomr/bomr.(properties|yaml)"); 63 | System.err.println(); 64 | System.exit(-1); 65 | } 66 | if (!this.bom.exists()) { 67 | System.err.println(); 68 | System.err.println("Fatal: bom file does not exist:"); 69 | System.err.println(); 70 | System.err.println(" " + this.bom.getAbsolutePath()); 71 | System.err.println(); 72 | System.err.println("Check your configuration in .bomr/bomr.(properties|yaml)"); 73 | System.err.println(); 74 | System.exit(-1); 75 | } 76 | new BomUpgrader(this.gitHub, new MavenMetadataVersionResolver(Arrays.asList("https://repo1.maven.org/maven2/")), 77 | this.properties.getPolicy(), this.properties.getProhibited()).upgrade(this.bom, 78 | this.properties.getGithub().getOrganization(), this.properties.getGithub().getRepository(), 79 | this.properties.getGithub().getIssueLabels(), arguments.getMilestone()); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradeCommandArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.IOException; 20 | 21 | import joptsimple.ArgumentAcceptingOptionSpec; 22 | import joptsimple.BuiltinHelpFormatter; 23 | import joptsimple.OptionParser; 24 | import joptsimple.OptionSet; 25 | 26 | /** 27 | * Command line arguments for the {@link UpgradeCommand}. 28 | * 29 | * @author Andy Wilkinson 30 | */ 31 | final class UpgradeCommandArguments { 32 | 33 | private final String milestone; 34 | 35 | private UpgradeCommandArguments(String milestone) { 36 | this.milestone = milestone; 37 | } 38 | 39 | static UpgradeCommandArguments parse(String[] args) { 40 | OptionParser optionParser = new OptionParser(); 41 | optionParser.formatHelpWith(new BuiltinHelpFormatter(120, 2)); 42 | ArgumentAcceptingOptionSpec milestoneSpec = optionParser 43 | .accepts("milestone", "Milestone to which upgrade issues are assigned").withRequiredArg() 44 | .ofType(String.class); 45 | try { 46 | OptionSet parsed = optionParser.parse(args); 47 | if (parsed.nonOptionArguments().size() != 0) { 48 | showUsageAndExit(optionParser); 49 | } 50 | return new UpgradeCommandArguments(parsed.valueOf(milestoneSpec)); 51 | } 52 | catch (Exception ex) { 53 | showUsageAndExit(optionParser); 54 | } 55 | return null; 56 | } 57 | 58 | private static void showUsageAndExit(OptionParser optionParser) { 59 | System.err.println("Usage: bomr upgrade []"); 60 | System.err.println(); 61 | try { 62 | optionParser.printHelpOn(System.err); 63 | } 64 | catch (IOException ex) { 65 | // Continue 66 | } 67 | System.err.println(); 68 | System.exit(-1); 69 | } 70 | 71 | String getMilestone() { 72 | return this.milestone; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradeConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import io.spring.bomr.BomrProperties; 20 | import io.spring.bomr.github.GitHub; 21 | 22 | import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; 23 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | /** 28 | * Configuration for Bomr's upgrade support. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | @Configuration 33 | @EnableConfigurationProperties(UpgradeProperties.class) 34 | class UpgradeConfiguration { 35 | 36 | @Bean 37 | public UpgradeCommand upgradeCommand(GitHub gitHub, UpgradeProperties upgradeProperties, 38 | BomrProperties bomrProperties) { 39 | return new UpgradeCommand(gitHub, upgradeProperties, bomrProperties.getBom()); 40 | } 41 | 42 | @Bean 43 | @ConfigurationPropertiesBinding 44 | public StringToVersionRangeConverter stringToVersionRangeConverter() { 45 | return new StringToVersionRangeConverter(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradePolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.function.BiPredicate; 20 | 21 | import io.spring.bomr.upgrade.version.DependencyVersion; 22 | 23 | /** 24 | * Policies used to decide which versions are considered as possible upgrades. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public enum UpgradePolicy implements BiPredicate { 29 | 30 | /** 31 | * All versions more recent than the current version will be suggested as possible 32 | * upgrades. 33 | */ 34 | ANY((candidate, current) -> current.compareTo(candidate) < 0), 35 | 36 | /** 37 | * New minor versions of the current major version will be suggested as possible 38 | * upgrades. For example, if the current version is 1.2.3, all 1.x.y versions after 39 | * 1.2.3 will be suggested. 2.x versions will not be offered. 40 | */ 41 | SAME_MAJOR_VERSION(DependencyVersion::isSameMajorAndNewerThan), 42 | 43 | /** 44 | * New patch versions of the current minor version will be offered as possible 45 | * upgrades. For example, if the current version is 1.2.3, all 1.2.x versions after 46 | * 1.2.3 will be suggested. 1.x versions will not be offered. 47 | */ 48 | SAME_MINOR_VERSION(DependencyVersion::isSameMinorAndNewerThan); 49 | 50 | private BiPredicate delegate; 51 | 52 | UpgradePolicy(BiPredicate delegate) { 53 | this.delegate = delegate; 54 | } 55 | 56 | @Override 57 | public boolean test(DependencyVersion candidate, DependencyVersion current) { 58 | return this.delegate.test(candidate, current); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradeProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import org.springframework.boot.context.properties.ConfigurationProperties; 23 | 24 | /** 25 | * Properties for configuring upgrades. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | @ConfigurationProperties(prefix = "bomr.upgrade", ignoreUnknownFields = false) 30 | public class UpgradeProperties { 31 | 32 | private final Github github = new Github(); 33 | 34 | private final List prohibited = new ArrayList<>(); 35 | 36 | /** 37 | * Policy that controls which versions are suggested as possible upgrades. 38 | */ 39 | private UpgradePolicy policy = UpgradePolicy.ANY; 40 | 41 | public UpgradePolicy getPolicy() { 42 | return this.policy; 43 | } 44 | 45 | public void setPolicy(UpgradePolicy policy) { 46 | this.policy = policy; 47 | } 48 | 49 | public Github getGithub() { 50 | return this.github; 51 | } 52 | 53 | public List getProhibited() { 54 | return this.prohibited; 55 | } 56 | 57 | /** 58 | * Properties related to GitHub. 59 | */ 60 | public static class Github { 61 | 62 | /** 63 | * Labels to apply to issues that are opened. 64 | */ 65 | private List issueLabels; 66 | 67 | /** 68 | * Organization on GitHub the owns the repository where issues should be opened. 69 | */ 70 | private String organization; 71 | 72 | /** 73 | * Repository on GitHub where issues should be opened. 74 | */ 75 | private String repository; 76 | 77 | public List getIssueLabels() { 78 | return this.issueLabels; 79 | } 80 | 81 | public void setIssueLabels(List issueLabels) { 82 | this.issueLabels = issueLabels; 83 | } 84 | 85 | public String getOrganization() { 86 | return this.organization; 87 | } 88 | 89 | public void setOrganization(String organization) { 90 | this.organization = organization; 91 | } 92 | 93 | public String getRepository() { 94 | return this.repository; 95 | } 96 | 97 | public void setRepository(String repository) { 98 | this.repository = repository; 99 | } 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/UpgradeResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.Collection; 20 | import java.util.List; 21 | 22 | /** 23 | * Resolves upgrades for {@link Project Projects}. 24 | * 25 | * @author Andy Wilkinson 26 | */ 27 | interface UpgradeResolver { 28 | 29 | /** 30 | * Resolves the upgrades to be applied to the given {@code projects}. 31 | * @param projects the projects 32 | * @return the upgrades 33 | */ 34 | List resolveUpgrades(Collection projects); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/VersionResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.util.SortedSet; 20 | 21 | import io.spring.bomr.upgrade.version.DependencyVersion; 22 | 23 | /** 24 | * Resolves the available versions for a {@link Module}. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | interface VersionResolver { 29 | 30 | /** 31 | * Resolves the available versions for the given {@code module}. 32 | * @param module the module 33 | * @return the available versions 34 | */ 35 | SortedSet resolveVersions(Module module); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/AbstractDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.apache.maven.artifact.versioning.ComparableVersion; 20 | 21 | /** 22 | * Base class for {@link DependencyVersion} implementations. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | abstract class AbstractDependencyVersion implements DependencyVersion { 27 | 28 | private final ComparableVersion comparableVersion; 29 | 30 | protected AbstractDependencyVersion(ComparableVersion comparableVersion) { 31 | this.comparableVersion = comparableVersion; 32 | } 33 | 34 | @Override 35 | public int compareTo(DependencyVersion other) { 36 | ComparableVersion otherComparable = (other instanceof AbstractDependencyVersion) 37 | ? ((AbstractDependencyVersion) other).comparableVersion : new ComparableVersion(other.toString()); 38 | return this.comparableVersion.compareTo(otherComparable); 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | if (this == obj) { 44 | return true; 45 | } 46 | if (obj == null) { 47 | return false; 48 | } 49 | if (getClass() != obj.getClass()) { 50 | return false; 51 | } 52 | AbstractDependencyVersion other = (AbstractDependencyVersion) obj; 53 | if (!this.comparableVersion.equals(other.comparableVersion)) { 54 | return false; 55 | } 56 | return true; 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return this.comparableVersion.hashCode(); 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return this.comparableVersion.toString(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/ArtifactVersionDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import java.util.Optional; 20 | 21 | import org.apache.maven.artifact.versioning.ArtifactVersion; 22 | import org.apache.maven.artifact.versioning.ComparableVersion; 23 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 24 | 25 | /** 26 | * A {@link DependencyVersion} backed by an {@link ArtifactVersion}. 27 | * 28 | * @author Andy Wilkinson 29 | */ 30 | class ArtifactVersionDependencyVersion extends AbstractDependencyVersion { 31 | 32 | private final ArtifactVersion artifactVersion; 33 | 34 | protected ArtifactVersionDependencyVersion(ArtifactVersion artifactVersion) { 35 | super(new ComparableVersion(artifactVersion.toString())); 36 | this.artifactVersion = artifactVersion; 37 | } 38 | 39 | protected ArtifactVersionDependencyVersion(ArtifactVersion artifactVersion, ComparableVersion comparableVersion) { 40 | super(comparableVersion); 41 | this.artifactVersion = artifactVersion; 42 | } 43 | 44 | @Override 45 | public boolean isNewerThan(DependencyVersion other) { 46 | if (other instanceof ReleaseTrainDependencyVersion) { 47 | return false; 48 | } 49 | return compareTo(other) > 0; 50 | } 51 | 52 | @Override 53 | public boolean isSameMajorAndNewerThan(DependencyVersion other) { 54 | if (other instanceof ReleaseTrainDependencyVersion) { 55 | return false; 56 | } 57 | return extractArtifactVersionDependencyVersion(other).map(this::isSameMajorAndNewerThan).orElse(true); 58 | } 59 | 60 | private boolean isSameMajorAndNewerThan(ArtifactVersionDependencyVersion other) { 61 | return this.artifactVersion.getMajorVersion() == other.artifactVersion.getMajorVersion() && isNewerThan(other); 62 | } 63 | 64 | @Override 65 | public boolean isSameMinorAndNewerThan(DependencyVersion other) { 66 | if (other instanceof ReleaseTrainDependencyVersion) { 67 | return false; 68 | } 69 | return extractArtifactVersionDependencyVersion(other).map(this::isSameMinorAndNewerThan).orElse(true); 70 | } 71 | 72 | private boolean isSameMinorAndNewerThan(ArtifactVersionDependencyVersion other) { 73 | return this.artifactVersion.getMajorVersion() == other.artifactVersion.getMajorVersion() 74 | && this.artifactVersion.getMinorVersion() == other.artifactVersion.getMinorVersion() 75 | && isNewerThan(other); 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return this.artifactVersion.toString(); 81 | } 82 | 83 | private Optional extractArtifactVersionDependencyVersion( 84 | DependencyVersion other) { 85 | ArtifactVersionDependencyVersion artifactVersion = null; 86 | if (other instanceof ArtifactVersionDependencyVersion) { 87 | artifactVersion = (ArtifactVersionDependencyVersion) other; 88 | } 89 | return Optional.ofNullable(artifactVersion); 90 | } 91 | 92 | static ArtifactVersionDependencyVersion parse(String version) { 93 | ArtifactVersion artifactVersion = new DefaultArtifactVersion(version); 94 | if (artifactVersion.getQualifier() != null && artifactVersion.getQualifier().equals(version)) { 95 | return null; 96 | } 97 | return new ArtifactVersionDependencyVersion(artifactVersion); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/CombinedPatchAndQualifierDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import java.util.regex.Matcher; 20 | import java.util.regex.Pattern; 21 | 22 | import org.apache.maven.artifact.versioning.ArtifactVersion; 23 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 24 | 25 | /** 26 | * A {@link DependencyVersion} where the patch and qualifier are not separated. 27 | * 28 | * @author Andy Wilkinson 29 | */ 30 | public class CombinedPatchAndQualifierDependencyVersion extends ArtifactVersionDependencyVersion { 31 | 32 | private static final Pattern PATTERN = Pattern.compile("([0-9]+\\.[0-9]+\\.[0-9]+)([A-Za-z][A-Za-z0-9]+)"); 33 | 34 | private final String original; 35 | 36 | public CombinedPatchAndQualifierDependencyVersion(ArtifactVersion artifactVersion, String original) { 37 | super(artifactVersion); 38 | this.original = original; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return this.original; 44 | } 45 | 46 | static CombinedPatchAndQualifierDependencyVersion parse(String version) { 47 | Matcher matcher = PATTERN.matcher(version); 48 | if (!matcher.matches()) { 49 | return null; 50 | } 51 | ArtifactVersion artifactVersion = new DefaultArtifactVersion(matcher.group(1) + "." + matcher.group(2)); 52 | if (artifactVersion.getQualifier() != null && artifactVersion.getQualifier().equals(version)) { 53 | return null; 54 | } 55 | return new CombinedPatchAndQualifierDependencyVersion(artifactVersion, version); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/DependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.function.Function; 22 | 23 | /** 24 | * Version of a dependency. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public interface DependencyVersion extends Comparable { 29 | 30 | /** 31 | * Returns whether this version is newer than the given {@code other} version. 32 | * @param other version to test 33 | * @return {@code true} if this version is newer, otherwise {@code false} 34 | */ 35 | boolean isNewerThan(DependencyVersion other); 36 | 37 | /** 38 | * Returns whether this version has the same major versions as the {@code other} 39 | * version while also being newer. 40 | * @param other version to test 41 | * @return {@code true} if this version has the same major and is newer, otherwise 42 | * {@code false} 43 | */ 44 | boolean isSameMajorAndNewerThan(DependencyVersion other); 45 | 46 | /** 47 | * Returns whether this version has the same major and minor versions as the 48 | * {@code other} version while also being newer. 49 | * @param other version to test 50 | * @return {@code true} if this version has the same major and minor and is newer, 51 | * otherwise {@code false} 52 | */ 53 | boolean isSameMinorAndNewerThan(DependencyVersion other); 54 | 55 | static DependencyVersion parse(String version) { 56 | List> parsers = Arrays.asList(ArtifactVersionDependencyVersion::parse, 57 | ReleaseTrainDependencyVersion::parse, NumericQualifierDependencyVersion::parse, 58 | CombinedPatchAndQualifierDependencyVersion::parse, LeadingZeroesDependencyVersion::parse, 59 | UnstructuredDependencyVersion::parse); 60 | for (Function parser : parsers) { 61 | DependencyVersion result = parser.apply(version); 62 | if (result != null) { 63 | return result; 64 | } 65 | } 66 | throw new IllegalArgumentException("Version '" + version + "' could not be parsed"); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/LeadingZeroesDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import java.util.regex.Matcher; 20 | import java.util.regex.Pattern; 21 | 22 | import org.apache.maven.artifact.versioning.ArtifactVersion; 23 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 24 | 25 | /** 26 | * A {@link DependencyVersion} that tolerates leading zeroes. 27 | * 28 | * @author Andy Wilkinson 29 | */ 30 | public class LeadingZeroesDependencyVersion extends ArtifactVersionDependencyVersion { 31 | 32 | private static final Pattern PATTERN = Pattern.compile("0*([0-9]+)\\.0*([0-9]+)\\.0*([0-9]+)"); 33 | 34 | private final String original; 35 | 36 | public LeadingZeroesDependencyVersion(ArtifactVersion artifactVersion, String original) { 37 | super(artifactVersion); 38 | this.original = original; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return this.original; 44 | } 45 | 46 | static LeadingZeroesDependencyVersion parse(String input) { 47 | Matcher matcher = PATTERN.matcher(input); 48 | if (!matcher.matches()) { 49 | return null; 50 | } 51 | ArtifactVersion artifactVersion = new DefaultArtifactVersion( 52 | matcher.group(1) + matcher.group(2) + matcher.group(3)); 53 | return new LeadingZeroesDependencyVersion(artifactVersion, input); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/NumericQualifierDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.apache.maven.artifact.versioning.ArtifactVersion; 20 | import org.apache.maven.artifact.versioning.ComparableVersion; 21 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 22 | 23 | /** 24 | * A fallback {@link DependencyVersion} to handle versions with four components that 25 | * cannot be handled by {@link ArtifactVersion} because the fourth component is numeric. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | final class NumericQualifierDependencyVersion extends ArtifactVersionDependencyVersion { 30 | 31 | private final String original; 32 | 33 | private NumericQualifierDependencyVersion(ArtifactVersion artifactVersion, String original) { 34 | super(artifactVersion, new ComparableVersion(original)); 35 | this.original = original; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return this.original; 41 | } 42 | 43 | static NumericQualifierDependencyVersion parse(String input) { 44 | String[] components = input.split("\\."); 45 | if (components.length == 4) { 46 | ArtifactVersion artifactVersion = new DefaultArtifactVersion( 47 | components[0] + "." + components[1] + "." + components[2]); 48 | if (artifactVersion.getQualifier() != null && artifactVersion.getQualifier().equals(input)) { 49 | return null; 50 | } 51 | return new NumericQualifierDependencyVersion(artifactVersion, input); 52 | } 53 | return null; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/ReleaseTrainDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import java.util.regex.Matcher; 20 | import java.util.regex.Pattern; 21 | 22 | import org.springframework.util.StringUtils; 23 | 24 | /** 25 | * A {@link DependencyVersion} for a release train such as Spring Data. 26 | * 27 | * @author Andy Wilkinson 28 | */ 29 | final class ReleaseTrainDependencyVersion implements DependencyVersion { 30 | 31 | private static final Pattern VERSION_PATTERN = Pattern.compile("([A-Z][a-z]+)-([A-Z]+)([0-9]*)"); 32 | 33 | private final String releaseTrain; 34 | 35 | private final String type; 36 | 37 | private final int version; 38 | 39 | private final String original; 40 | 41 | private ReleaseTrainDependencyVersion(String releaseTrain, String type, int version, String original) { 42 | this.releaseTrain = releaseTrain; 43 | this.type = type; 44 | this.version = version; 45 | this.original = original; 46 | } 47 | 48 | @Override 49 | public int compareTo(DependencyVersion other) { 50 | if (!(other instanceof ReleaseTrainDependencyVersion)) { 51 | return -1; 52 | } 53 | ReleaseTrainDependencyVersion otherReleaseTrain = (ReleaseTrainDependencyVersion) other; 54 | int comparison = this.releaseTrain.compareTo(otherReleaseTrain.releaseTrain); 55 | if (comparison != 0) { 56 | return comparison; 57 | } 58 | comparison = this.type.compareTo(otherReleaseTrain.type); 59 | if (comparison != 0) { 60 | return comparison; 61 | } 62 | return Integer.compare(this.version, otherReleaseTrain.version); 63 | } 64 | 65 | @Override 66 | public boolean isNewerThan(DependencyVersion other) { 67 | if (!(other instanceof ReleaseTrainDependencyVersion)) { 68 | return true; 69 | } 70 | ReleaseTrainDependencyVersion otherReleaseTrain = (ReleaseTrainDependencyVersion) other; 71 | return otherReleaseTrain.compareTo(this) < 0; 72 | } 73 | 74 | @Override 75 | public boolean isSameMajorAndNewerThan(DependencyVersion other) { 76 | return isNewerThan(other); 77 | } 78 | 79 | @Override 80 | public boolean isSameMinorAndNewerThan(DependencyVersion other) { 81 | if (!(other instanceof ReleaseTrainDependencyVersion)) { 82 | return true; 83 | } 84 | ReleaseTrainDependencyVersion otherReleaseTrain = (ReleaseTrainDependencyVersion) other; 85 | return otherReleaseTrain.releaseTrain.equals(this.releaseTrain) && isNewerThan(other); 86 | } 87 | 88 | @Override 89 | public boolean equals(Object obj) { 90 | if (this == obj) { 91 | return true; 92 | } 93 | if (obj == null) { 94 | return false; 95 | } 96 | if (getClass() != obj.getClass()) { 97 | return false; 98 | } 99 | ReleaseTrainDependencyVersion other = (ReleaseTrainDependencyVersion) obj; 100 | if (!this.original.equals(other.original)) { 101 | return false; 102 | } 103 | return true; 104 | } 105 | 106 | @Override 107 | public int hashCode() { 108 | return this.original.hashCode(); 109 | } 110 | 111 | @Override 112 | public String toString() { 113 | return this.original; 114 | } 115 | 116 | static ReleaseTrainDependencyVersion parse(String input) { 117 | Matcher matcher = VERSION_PATTERN.matcher(input); 118 | if (!matcher.matches()) { 119 | return null; 120 | } 121 | return new ReleaseTrainDependencyVersion(matcher.group(1), matcher.group(2), 122 | (StringUtils.hasLength(matcher.group(3))) ? Integer.parseInt(matcher.group(3)) : 0, input); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/upgrade/version/UnstructuredDependencyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.apache.maven.artifact.versioning.ComparableVersion; 20 | 21 | /** 22 | * A {@link DependencyVersion} with no structure such that version comparisons are not 23 | * possible. 24 | * 25 | * @author Andy Wilkinson 26 | */ 27 | public class UnstructuredDependencyVersion extends AbstractDependencyVersion implements DependencyVersion { 28 | 29 | private final String version; 30 | 31 | public UnstructuredDependencyVersion(String version) { 32 | super(new ComparableVersion(version)); 33 | this.version = version; 34 | } 35 | 36 | @Override 37 | public boolean isNewerThan(DependencyVersion other) { 38 | return this.compareTo(other) > 0; 39 | } 40 | 41 | @Override 42 | public boolean isSameMajorAndNewerThan(DependencyVersion other) { 43 | return this.compareTo(other) > 0; 44 | } 45 | 46 | @Override 47 | public boolean isSameMinorAndNewerThan(DependencyVersion other) { 48 | return this.compareTo(other) > 0; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return this.version; 54 | } 55 | 56 | static UnstructuredDependencyVersion parse(String version) { 57 | return new UnstructuredDependencyVersion(version); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/BomVerifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.File; 20 | import java.io.FileWriter; 21 | import java.net.URI; 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.Properties; 27 | import java.util.Set; 28 | import java.util.stream.Collectors; 29 | 30 | import com.samskivert.mustache.Mustache; 31 | import com.samskivert.mustache.Mustache.Compiler; 32 | import com.samskivert.mustache.Mustache.TemplateLoader; 33 | import com.samskivert.mustache.Template; 34 | import io.spring.bomr.verify.MavenInvoker.MavenInvocationFailedException; 35 | 36 | import org.springframework.util.StringUtils; 37 | 38 | /** 39 | * Verifies a Maven bom by checking that all of its managed dependencies can be resolved. 40 | * 41 | * @author Andy Wilkinson 42 | */ 43 | class BomVerifier { 44 | 45 | private final MavenInvoker mavenInvoker; 46 | 47 | private final Compiler compiler; 48 | 49 | private final TemplateLoader templateLoader; 50 | 51 | BomVerifier(MavenInvoker mavenInvoker, Compiler compiler, TemplateLoader templateLoader) { 52 | this.mavenInvoker = mavenInvoker; 53 | this.compiler = compiler; 54 | this.templateLoader = templateLoader; 55 | } 56 | 57 | void verify(File bom, Set ignoredDependencies, Set repositoryUris) { 58 | VerifiableBom verifiableBom = new VerifiableBom(this.mavenInvoker, bom); 59 | List dependenciesToVerify = verifiableBom.getManagedDependencies().stream() 60 | .filter((dependency) -> !ignoredDependencies 61 | .contains(dependency.getGroupId() + ":" + dependency.getArtifactId())) 62 | .collect(Collectors.toList()); 63 | File dependenciesPom = createDependenciesPom(bom, verifiableBom, dependenciesToVerify, 64 | repositoryUris.stream().map(Repository::new).collect(Collectors.toList())); 65 | System.out.print("Verifying " + dependenciesToVerify.size() + " dependencies..."); 66 | try { 67 | this.mavenInvoker.invoke(dependenciesPom, new Properties(), "dependency:list"); 68 | System.out.println(" Done."); 69 | } 70 | catch (MavenInvocationFailedException ex) { 71 | System.err.println(); 72 | System.err.println("Dependency resolution failed:"); 73 | System.err.println(); 74 | ex.getOutputLines().forEach(System.err::println); 75 | } 76 | } 77 | 78 | private File createDependenciesPom(File bomFile, VerifiableBom bom, List dependenciesToVerify, 79 | List additionalRepositories) { 80 | try { 81 | Template template = this.compiler.compile(this.templateLoader.getTemplate("bom-dependencies")); 82 | Map context = new HashMap<>(); 83 | context.put("dependencies", dependenciesToVerify); 84 | List repositories = new ArrayList<>(bom.getRepositories()); 85 | repositories.addAll(additionalRepositories); 86 | context.put("repositories", repositories); 87 | context.put("parentGroupId", bom.getGroupId()); 88 | context.put("parentArtifactId", bom.getArtifactId()); 89 | context.put("parentVersion", bom.getVersion()); 90 | context.put("parentRelativePath", bomFile.getAbsolutePath()); 91 | context.put("classifierIfAvailable", (Mustache.Lambda) (frag, out) -> { 92 | String classifier = frag.execute(); 93 | if (StringUtils.hasText(classifier)) { 94 | out.append(""); 95 | out.append(classifier); 96 | out.append("\n"); 97 | } 98 | }); 99 | File dependenciesPom = File.createTempFile("dependencies-", ".pom"); 100 | try (FileWriter writer = new FileWriter(dependenciesPom)) { 101 | template.execute(context, writer); 102 | } 103 | return dependenciesPom; 104 | } 105 | catch (Exception ex) { 106 | throw new RuntimeException(ex); 107 | } 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/ManagedDependency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import org.springframework.util.StringUtils; 20 | 21 | /** 22 | * Details of a dependency managed by a bom. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | class ManagedDependency { 27 | 28 | private final String groupId; 29 | 30 | private final String artifactId; 31 | 32 | private final String classifier; 33 | 34 | private final String type; 35 | 36 | ManagedDependency(String groupId, String artifactId, String classifier, String type) { 37 | this.groupId = groupId; 38 | this.artifactId = artifactId; 39 | this.classifier = classifier; 40 | this.type = StringUtils.hasText(type) ? type : "jar"; 41 | } 42 | 43 | String getGroupId() { 44 | return this.groupId; 45 | } 46 | 47 | String getArtifactId() { 48 | return this.artifactId; 49 | } 50 | 51 | String getClassifier() { 52 | return this.classifier; 53 | } 54 | 55 | String getType() { 56 | return this.type; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/MavenInvoker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.File; 21 | import java.io.PrintStream; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | import java.util.Properties; 26 | 27 | import org.apache.maven.shared.invoker.DefaultInvocationRequest; 28 | import org.apache.maven.shared.invoker.DefaultInvoker; 29 | import org.apache.maven.shared.invoker.InvocationOutputHandler; 30 | import org.apache.maven.shared.invoker.InvocationResult; 31 | import org.apache.maven.shared.invoker.InvokerLogger; 32 | import org.apache.maven.shared.invoker.PrintStreamLogger; 33 | 34 | /** 35 | * A {@code MavenInvoker} can be used to programmatically invoke Maven. 36 | * 37 | * @author Andy Wilkinson 38 | */ 39 | class MavenInvoker { 40 | 41 | private final File mavenHome; 42 | 43 | MavenInvoker(File mavenHome) { 44 | this.mavenHome = mavenHome; 45 | } 46 | 47 | void invoke(File pom, Properties properties, String... goals) throws MavenInvocationFailedException { 48 | DefaultInvocationRequest invocation = new DefaultInvocationRequest(); 49 | invocation.setPomFile(pom); 50 | invocation.setGoals(Arrays.asList(goals)); 51 | invocation.setProperties(properties); 52 | invocation.setUpdateSnapshots(true); 53 | CapturingInvocationOutputHandler outputHandler = new CapturingInvocationOutputHandler(); 54 | invocation.setOutputHandler(outputHandler); 55 | DefaultInvoker invoker = new DefaultInvoker(); 56 | invoker.setLogger( 57 | new PrintStreamLogger(new PrintStream(new ByteArrayOutputStream(), true), InvokerLogger.FATAL)); 58 | invoker.setMavenHome(this.mavenHome); 59 | InvocationResult result; 60 | try { 61 | result = invoker.execute(invocation); 62 | } 63 | catch (Exception ex) { 64 | throw new RuntimeException(ex); 65 | } 66 | if (result.getExitCode() != 0) { 67 | throw new MavenInvocationFailedException(outputHandler.lines); 68 | } 69 | } 70 | 71 | /** 72 | * Exception thrown when an invocation of Maven fails. 73 | */ 74 | @SuppressWarnings("serial") 75 | static final class MavenInvocationFailedException extends Exception { 76 | 77 | private final List outputLines; 78 | 79 | MavenInvocationFailedException(List outputLines) { 80 | this.outputLines = outputLines; 81 | } 82 | 83 | List getOutputLines() { 84 | return this.outputLines; 85 | } 86 | 87 | } 88 | 89 | private final class CapturingInvocationOutputHandler implements InvocationOutputHandler { 90 | 91 | private final List lines = new ArrayList<>(); 92 | 93 | @Override 94 | public void consumeLine(String line) { 95 | this.lines.add(line); 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/MavenProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.File; 20 | 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | 23 | /** 24 | * Properties for configuring Maven. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | @ConfigurationProperties("bomr.maven") 29 | public class MavenProperties { 30 | 31 | /** 32 | * Maven's home directory. 33 | */ 34 | private File home; 35 | 36 | /** 37 | * Returns the location of Maven's home directory. 38 | * @return the home directory 39 | */ 40 | public File getHome() { 41 | return this.home; 42 | } 43 | 44 | /** 45 | * Sets the location of Maven's home directory. 46 | * @param home the home directory 47 | */ 48 | public void setHome(File home) { 49 | this.home = home; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/Repository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.net.URI; 20 | 21 | /** 22 | * Representation of a repository that can be declared in a Maven pom. 23 | * 24 | * @author Andy Wilkinson 25 | */ 26 | final class Repository { 27 | 28 | private final String id; 29 | 30 | private final URI url; 31 | 32 | private final boolean snapshotsEnabled; 33 | 34 | Repository(URI url) { 35 | this.id = (url.getHost() + "-" + url.getPath()).replace("/", "-"); 36 | this.url = url; 37 | this.snapshotsEnabled = false; 38 | } 39 | 40 | Repository(String id, URI url, boolean snapshotsEnabled) { 41 | this.id = id; 42 | this.url = url; 43 | this.snapshotsEnabled = snapshotsEnabled; 44 | } 45 | 46 | /** 47 | * Returns the id of the repository. 48 | * @return the id 49 | */ 50 | public String getId() { 51 | return this.id; 52 | } 53 | 54 | /** 55 | * Returns the URL of the repository. 56 | * @return the URL 57 | */ 58 | public URI getUrl() { 59 | return this.url; 60 | } 61 | 62 | /** 63 | * Whether snapshots are enabled for the repository. 64 | * @return {@code true} if snapshots are enabled, otherwise {@code false} 65 | */ 66 | public boolean isSnapshotsEnabled() { 67 | return this.snapshotsEnabled; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/VerifiableBom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.net.URI; 22 | import java.util.List; 23 | import java.util.Properties; 24 | import java.util.function.BiFunction; 25 | import java.util.stream.Collectors; 26 | import java.util.stream.IntStream; 27 | 28 | import javax.xml.parsers.DocumentBuilder; 29 | import javax.xml.parsers.DocumentBuilderFactory; 30 | import javax.xml.xpath.XPath; 31 | import javax.xml.xpath.XPathConstants; 32 | import javax.xml.xpath.XPathExpressionException; 33 | import javax.xml.xpath.XPathFactory; 34 | 35 | import io.spring.bomr.verify.MavenInvoker.MavenInvocationFailedException; 36 | import org.apache.maven.shared.invoker.MavenInvocationException; 37 | import org.w3c.dom.Document; 38 | import org.w3c.dom.Node; 39 | import org.w3c.dom.NodeList; 40 | 41 | /** 42 | * A representation of a Maven bom intended for verification. 43 | * 44 | * @author Andy Wilkinson 45 | */ 46 | class VerifiableBom { 47 | 48 | private final List managedDependencies; 49 | 50 | private final List repositories; 51 | 52 | private final String groupId; 53 | 54 | private final String artifactId; 55 | 56 | private final String version; 57 | 58 | VerifiableBom(MavenInvoker mavenInvoker, File bomFile) { 59 | try { 60 | File effectiveBomFile = createEffectiveBomFile(mavenInvoker, bomFile); 61 | Document effectiveBom = parseBom(effectiveBomFile); 62 | XPath xpath = XPathFactory.newInstance().newXPath(); 63 | this.managedDependencies = asList(xpath, "/project/dependencyManagement/dependencies/dependency", 64 | effectiveBom, this::createManagedDependency); 65 | this.groupId = xpath.evaluate("/project/groupId/text()", effectiveBom); 66 | this.artifactId = xpath.evaluate("/project/artifactId/text()", effectiveBom); 67 | this.version = xpath.evaluate("/project/version/text()", effectiveBom); 68 | this.repositories = asList(xpath, "/project/repositories/repository", effectiveBom, this::createRepository); 69 | } 70 | catch (Exception ex) { 71 | throw new RuntimeException(ex); 72 | } 73 | } 74 | 75 | public List getManagedDependencies() { 76 | return this.managedDependencies; 77 | } 78 | 79 | public List getRepositories() { 80 | return this.repositories; 81 | } 82 | 83 | String getGroupId() { 84 | return this.groupId; 85 | } 86 | 87 | String getArtifactId() { 88 | return this.artifactId; 89 | } 90 | 91 | String getVersion() { 92 | return this.version; 93 | } 94 | 95 | private List asList(XPath xpath, String expression, Document effectiveBom, BiFunction mapper) 96 | throws Exception { 97 | NodeList nodeList = (NodeList) xpath.evaluate(expression, effectiveBom, XPathConstants.NODESET); 98 | return IntStream.range(0, nodeList.getLength()).mapToObj(nodeList::item) 99 | .map((node) -> mapper.apply(xpath, node)).collect(Collectors.toList()); 100 | } 101 | 102 | private ManagedDependency createManagedDependency(XPath xpath, Node node) { 103 | try { 104 | String groupId = xpath.evaluate("groupId/text()", node); 105 | String artifactId = xpath.evaluate("artifactId/text()", node); 106 | String classifier = xpath.evaluate("classifier/text()", node); 107 | String type = xpath.evaluate("type/text()", node); 108 | return new ManagedDependency(groupId, artifactId, classifier, type); 109 | } 110 | catch (XPathExpressionException ex) { 111 | throw new RuntimeException(ex); 112 | } 113 | } 114 | 115 | private Repository createRepository(XPath xpath, Node node) { 116 | try { 117 | String id = xpath.evaluate("id/text()", node); 118 | String url = xpath.evaluate("url/text()", node); 119 | boolean snapshotsEnabled = Boolean.valueOf(xpath.evaluate("snapshots/enabled/text()", node)); 120 | return new Repository(id, URI.create(url), snapshotsEnabled); 121 | } 122 | catch (XPathExpressionException ex) { 123 | throw new RuntimeException(ex); 124 | } 125 | } 126 | 127 | private File createEffectiveBomFile(MavenInvoker mavenInvoker, File bomFile) 128 | throws IOException, MavenInvocationException { 129 | File effectiveBomFile = File.createTempFile("effective-", ".pom"); 130 | Properties properties = new Properties(); 131 | properties.setProperty("output", effectiveBomFile.getAbsolutePath()); 132 | try { 133 | mavenInvoker.invoke(bomFile, properties, "help:effective-pom"); 134 | return effectiveBomFile; 135 | } 136 | catch (MavenInvocationFailedException ex) { 137 | System.err.println("Failed to create effective bom from '" + bomFile.getAbsolutePath() + "':"); 138 | ex.getOutputLines().forEach(System.err::println); 139 | System.exit(-1); 140 | return null; 141 | } 142 | } 143 | 144 | private Document parseBom(File bomFile) { 145 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 146 | try { 147 | DocumentBuilder builder = factory.newDocumentBuilder(); 148 | return builder.parse(bomFile); 149 | } 150 | catch (Exception ex) { 151 | throw new RuntimeException(ex); 152 | } 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/VerificationConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import com.samskivert.mustache.Mustache.Compiler; 20 | import com.samskivert.mustache.Mustache.TemplateLoader; 21 | import io.spring.bomr.BomrProperties; 22 | 23 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | /** 28 | * Configuration for bom verification. 29 | * 30 | * @author Andy Wilkinson 31 | */ 32 | @Configuration 33 | @EnableConfigurationProperties({ MavenProperties.class, VerifyProperties.class }) 34 | class VerificationConfiguration { 35 | 36 | @Bean 37 | public VerifyCommand verifyCommand(BomrProperties bomr, MavenProperties maven, VerifyProperties verify, 38 | Compiler compiler, TemplateLoader templateLoader) { 39 | return new VerifyCommand(new BomVerifier(new MavenInvoker(maven.getHome()), compiler, templateLoader), 40 | bomr.getBom(), verify.getIgnoredDependencies(), verify.getRepositories()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/VerifyCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.File; 20 | import java.net.URI; 21 | import java.util.Set; 22 | 23 | import io.spring.bomr.Command; 24 | 25 | /** 26 | * A {@link Command} to verify a bom. Verification is performed by checking that every 27 | * dependency that is managed by the bom can be resolved. 28 | * 29 | * @author Andy Wilkinson 30 | */ 31 | class VerifyCommand implements Command { 32 | 33 | private final BomVerifier verifier; 34 | 35 | private final File bom; 36 | 37 | private final Set ignoredDependencies; 38 | 39 | private final Set repositories; 40 | 41 | VerifyCommand(BomVerifier verifier, File bom, Set ignoredDependencies, Set repositories) { 42 | this.verifier = verifier; 43 | this.bom = bom; 44 | this.ignoredDependencies = ignoredDependencies; 45 | this.repositories = repositories; 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return "verify"; 51 | } 52 | 53 | @Override 54 | public String getDescription() { 55 | return "Verifies the dependencies managed by a bom"; 56 | } 57 | 58 | @Override 59 | public void invoke(String[] args) { 60 | if (this.bom == null) { 61 | System.err.println(); 62 | System.err.println("Fatal: bomr.bom has not been configured"); 63 | System.err.println(); 64 | System.err.println("Check your onfiguration in .bomr/bomr.(properties|yaml)"); 65 | System.err.println(); 66 | System.exit(-1); 67 | } 68 | if (!this.bom.exists()) { 69 | System.err.println(); 70 | System.err.println("Fatal: bom file does not exist:"); 71 | System.err.println(); 72 | System.err.println(" " + this.bom.getAbsolutePath()); 73 | System.err.println(); 74 | System.err.println("Check your onfiguration in .bomr/bomr.(properties|yaml)"); 75 | System.err.println(); 76 | System.exit(-1); 77 | } 78 | this.verifier.verify(this.bom, this.ignoredDependencies, this.repositories); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/VerifyCommandArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.io.IOException; 20 | import java.net.URI; 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | 24 | import joptsimple.ArgumentAcceptingOptionSpec; 25 | import joptsimple.BuiltinHelpFormatter; 26 | import joptsimple.OptionParser; 27 | import joptsimple.OptionSet; 28 | 29 | /** 30 | * Command line arguments for the {@link VerifyCommand}. 31 | * 32 | * @author Andy Wilkinson 33 | */ 34 | final class VerifyCommandArguments { 35 | 36 | private final Set ignores; 37 | 38 | private final Set repositoryUris; 39 | 40 | private VerifyCommandArguments(Set ignores, Set repositoryUris) { 41 | this.ignores = ignores; 42 | this.repositoryUris = repositoryUris; 43 | } 44 | 45 | static VerifyCommandArguments parse(String[] args) { 46 | OptionParser optionParser = new OptionParser(); 47 | optionParser.formatHelpWith(new BuiltinHelpFormatter(120, 2)); 48 | ArgumentAcceptingOptionSpec ignoreSpec = optionParser 49 | .accepts("ignore", "groupId:artifactId of a managed dependency to ignore").withRequiredArg() 50 | .ofType(String.class); 51 | ArgumentAcceptingOptionSpec repositorySpec = optionParser 52 | .accepts("repository", "Additional repository to use for dependency resolution").withRequiredArg() 53 | .ofType(URI.class); 54 | try { 55 | OptionSet parsed = optionParser.parse(args); 56 | if (parsed.nonOptionArguments().size() != 0) { 57 | showUsageAndExit(optionParser); 58 | } 59 | return new VerifyCommandArguments(new HashSet<>(parsed.valuesOf(ignoreSpec)), 60 | new HashSet<>(parsed.valuesOf(repositorySpec))); 61 | } 62 | catch (Exception ex) { 63 | showUsageAndExit(optionParser); 64 | } 65 | return null; 66 | } 67 | 68 | private static void showUsageAndExit(OptionParser optionParser) { 69 | System.err.println("Usage: bomr verify []"); 70 | System.err.println(); 71 | try { 72 | optionParser.printHelpOn(System.err); 73 | } 74 | catch (IOException ex) { 75 | // Continue 76 | } 77 | System.err.println(); 78 | System.exit(-1); 79 | } 80 | 81 | Set getIgnores() { 82 | return this.ignores; 83 | } 84 | 85 | Set getRepositoryUris() { 86 | return this.repositoryUris; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/io/spring/bomr/verify/VerifyProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.verify; 18 | 19 | import java.net.URI; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | import org.springframework.boot.context.properties.ConfigurationProperties; 24 | 25 | /** 26 | * {@link ConfigurationProperties Configuration properties} for bom verification. 27 | * 28 | * @author Andy Wilkinson 29 | */ 30 | @ConfigurationProperties(prefix = "bomr.verify", ignoreUnknownFields = false) 31 | public class VerifyProperties { 32 | 33 | /** 34 | * Dependencies (groupId:artifactId) to be ignored when verifying the bom. 35 | */ 36 | private final Set ignoredDependencies = new HashSet<>(); 37 | 38 | /** 39 | * Additional repositories to use for dependency resolution when verifying the bom. 40 | */ 41 | private final Set repositories = new HashSet<>(); 42 | 43 | public Set getIgnoredDependencies() { 44 | return this.ignoredDependencies; 45 | } 46 | 47 | public Set getRepositories() { 48 | return this.repositories; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.env.EnvironmentPostProcessor=io.spring.bomr.UserHomeBomrPropertiesEnvironmentPostProcessor -------------------------------------------------------------------------------- /src/main/resources/templates/bom-dependencies.mustache: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | {{parentGroupId}} 8 | {{parentArtifactId}} 9 | {{parentVersion}} 10 | {{parentRelativePath}} 11 | 12 | 13 | {{parentGroupId}} 14 | {{parentArtifactId}}-verification 15 | {{parentVersion}} 16 | pom 17 | 18 | 19 | {{#dependencies}} 20 | 21 | {{groupId}} 22 | {{artifactId}} 23 | {{type}} 24 | {{#classifierIfAvailable}}{{classifier}}{{/classifierIfAvailable}} 25 | 26 | {{/dependencies}} 27 | 28 | 29 | 30 | {{#repositories}} 31 | 32 | {{id}} 33 | {{url}} 34 | 35 | {{snapshotsEnabled}} 36 | 37 | 38 | {{/repositories}} 39 | 40 | 41 | 42 | 43 | 44 | kr.motd.maven 45 | os-maven-plugin 46 | 1.6.1 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/CommandsTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr; 18 | 19 | import java.util.Arrays; 20 | import java.util.Collections; 21 | 22 | import org.junit.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * Tests for {@link Commands}. 28 | * 29 | * @author Andy Wilkinson 30 | */ 31 | public class CommandsTests { 32 | 33 | @Test 34 | public void commandsAreAvailableByName() { 35 | Command alpha = mockCommand("alpha"); 36 | Command bravo = mockCommand("bravo"); 37 | Command charlie = mockCommand("charlie"); 38 | Commands commands = new Commands(Arrays.asList(charlie, bravo, alpha)); 39 | assertThat(commands.get("bravo")).isEqualTo(bravo); 40 | } 41 | 42 | @Test 43 | public void unknownCommandReturnsNull() { 44 | Commands commands = new Commands(Collections.emptyList()); 45 | assertThat(commands.get("foo")).isNull(); 46 | } 47 | 48 | @Test 49 | public void commandsAreDescribedAlphabetically() { 50 | Command alpha = mockCommand("alpha", "Description of alpha"); 51 | Command bravo = mockCommand("bravo", "Description of bravo"); 52 | Command charlie = mockCommand("charlie", "Description of charlie"); 53 | Commands commands = new Commands(Arrays.asList(charlie, bravo, alpha)); 54 | String description = commands.describe(); 55 | assertThat(description).isEqualTo(String.format(" alpha Description of alpha%n" 56 | + " bravo Description of bravo%n" + " charlie Description of charlie%n")); 57 | } 58 | 59 | private Command mockCommand(String name) { 60 | return mockCommand(name, null); 61 | } 62 | 63 | private Command mockCommand(String name, String description) { 64 | return new MockCommand(name, description); 65 | } 66 | 67 | private static final class MockCommand implements Command { 68 | 69 | private final String name; 70 | 71 | private final String description; 72 | 73 | MockCommand(String name, String description) { 74 | this.name = name; 75 | this.description = description; 76 | } 77 | 78 | @Override 79 | public String getName() { 80 | return this.name; 81 | } 82 | 83 | @Override 84 | public String getDescription() { 85 | return this.description; 86 | } 87 | 88 | @Override 89 | public void invoke(String[] args) { 90 | 91 | } 92 | 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/artifacts/MavenCentralSearchArtifactsFinderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.io.File; 20 | import java.util.Set; 21 | 22 | import org.junit.Test; 23 | 24 | import org.springframework.core.io.FileSystemResource; 25 | import org.springframework.http.HttpMethod; 26 | import org.springframework.http.MediaType; 27 | import org.springframework.test.web.client.MockRestServiceServer; 28 | import org.springframework.web.client.RestTemplate; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; 32 | import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; 33 | import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; 34 | 35 | /** 36 | * Tests for {@link MavenCentralSearchArtifactsFinder}. 37 | * 38 | * @author Andy Wilkinson 39 | */ 40 | public class MavenCentralSearchArtifactsFinderTests { 41 | 42 | private final RestTemplate rest = new RestTemplate(); 43 | 44 | private final MockRestServiceServer server = MockRestServiceServer.bindTo(this.rest).ignoreExpectOrder(true) 45 | .build(); 46 | 47 | @Test 48 | public void findReturnsNamesOfArtifactsWithMatchingVersionAndJarArtifact() { 49 | configureExpectations(new File("src/test/resources/artifacts/org/quartz-scheduler/")); 50 | Set artifacts = new MavenCentralSearchArtifactsFinder(this.rest).find("org.infinispan", "9.4.15.Final"); 51 | assertThat(artifacts).hasSize(82); 52 | } 53 | 54 | private void configureExpectations(File root) { 55 | for (int i = 0; i < 7; i++) { 56 | this.server.expect(requestTo( 57 | "https://search.maven.org/solrsearch/select?q=g:org.infinispan+AND+v:9.4.15.Final&rows=20&start=" 58 | + (i * 20))) 59 | .andExpect(method(HttpMethod.GET)) 60 | .andRespond(withSuccess( 61 | new FileSystemResource( 62 | new File("src/test/resources/artifacts/org/infinispan/page" + (i + 1) + ".json")), 63 | MediaType.APPLICATION_JSON)); 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/artifacts/MavenRepositoryArtifactsFinderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.artifacts; 18 | 19 | import java.io.File; 20 | import java.net.URI; 21 | import java.util.Set; 22 | 23 | import org.junit.Test; 24 | 25 | import org.springframework.core.io.FileSystemResource; 26 | import org.springframework.http.HttpMethod; 27 | import org.springframework.http.HttpStatus; 28 | import org.springframework.http.MediaType; 29 | import org.springframework.test.web.client.MockRestServiceServer; 30 | import org.springframework.web.client.RestTemplate; 31 | 32 | import static org.assertj.core.api.Assertions.assertThat; 33 | import static org.hamcrest.CoreMatchers.endsWith; 34 | import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; 35 | import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; 36 | import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; 37 | import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; 38 | 39 | /** 40 | * Tests for {@link MavenRepositoryArtifactsFinder}. 41 | * 42 | * @author Andy Wilkinson 43 | */ 44 | public class MavenRepositoryArtifactsFinderTests { 45 | 46 | private final RestTemplate rest = new RestTemplate(); 47 | 48 | private final MockRestServiceServer server = MockRestServiceServer.bindTo(this.rest).ignoreExpectOrder(true) 49 | .build(); 50 | 51 | @Test 52 | public void findReturnsNamesOfArtifactsWithMatchingVersionAndJarArtifact() { 53 | configureExpectations(new File("src/test/resources/artifacts/org/quartz-scheduler/")); 54 | Set artifacts = new MavenRepositoryArtifactsFinder(this.rest, 55 | URI.create("https://repo1.maven.org/maven2/")).find("org.quartz-scheduler", "2.3.0"); 56 | assertThat(artifacts).containsExactly("quartz", "quartz-jobs"); 57 | } 58 | 59 | private void configureExpectations(File root) { 60 | configureExpectations(root, "https://repo1.maven.org/maven2/org/quartz-scheduler/"); 61 | this.server.expect(requestTo(endsWith(".jar"))).andRespond(withStatus(HttpStatus.NOT_FOUND)); 62 | } 63 | 64 | private void configureExpectations(File source, String base) { 65 | for (File candidate : source.listFiles()) { 66 | if (candidate.isFile()) { 67 | if ("index.html".equals(candidate.getName())) { 68 | this.server.expect(requestTo(base)).andExpect(method(HttpMethod.GET)) 69 | .andRespond(withSuccess(new FileSystemResource(candidate), MediaType.TEXT_HTML)); 70 | } 71 | else if (candidate.getName().endsWith(".jar")) { 72 | this.server.expect(requestTo(base + candidate.getName())).andExpect(method(HttpMethod.HEAD)) 73 | .andRespond(withSuccess()); 74 | } 75 | } 76 | else { 77 | configureExpectations(candidate, base + candidate.getName() + "/"); 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/BomVersionsTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.StringReader; 20 | 21 | import javax.xml.parsers.DocumentBuilderFactory; 22 | 23 | import io.spring.bomr.upgrade.BomVersions.BomVersion; 24 | import org.junit.Test; 25 | import org.w3c.dom.Document; 26 | import org.xml.sax.InputSource; 27 | 28 | import static org.assertj.core.api.Assertions.assertThat; 29 | 30 | /** 31 | * Tests for {@link BomVersions}. 32 | * 33 | * @author Andy Wilkinson 34 | */ 35 | public class BomVersionsTests { 36 | 37 | @Test 38 | public void versionIsResolvedFromProperties() throws Exception { 39 | Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder() 40 | .parse(new InputSource(new StringReader("1.2.3" 41 | + "2.3.4" + ""))); 42 | BomVersions versions = new BomVersions(document); 43 | BomVersion fooVersion = versions.resolve("${foo}"); 44 | assertThat(fooVersion.getProperty()).isEqualTo("foo"); 45 | assertThat(fooVersion.getVersion().toString()).isEqualTo("1.2.3"); 46 | BomVersion barVersion = versions.resolve("${bar.version}"); 47 | assertThat(barVersion.getProperty()).isEqualTo("bar.version"); 48 | assertThat(barVersion.getVersion().toString()).isEqualTo("2.3.4"); 49 | } 50 | 51 | @Test 52 | public void unknownVersionResolvesToNull() throws Exception { 53 | Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder() 54 | .parse(new InputSource(new StringReader("1.2.3" 55 | + "2.3.4" + ""))); 56 | BomVersions versions = new BomVersions(document); 57 | assertThat(versions.resolve("${baz.version}")).isNull(); 58 | } 59 | 60 | @Test 61 | public void indirectVersionsAreResolved() throws Exception { 62 | Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder() 63 | .parse(new InputSource(new StringReader("1.2.3" 64 | + "${foo}" + ""))); 65 | BomVersions versions = new BomVersions(document); 66 | BomVersion barVersion = versions.resolve("${bar.version}"); 67 | assertThat(barVersion.getProperty()).isEqualTo("foo"); 68 | assertThat(barVersion.getVersion().toString()).isEqualTo("1.2.3"); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/MavenMetadataVersionResolverTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import java.io.File; 20 | import java.util.Arrays; 21 | import java.util.Set; 22 | import java.util.stream.Collectors; 23 | 24 | import io.spring.bomr.upgrade.version.DependencyVersion; 25 | import org.junit.Test; 26 | 27 | import org.springframework.core.io.FileSystemResource; 28 | import org.springframework.http.HttpMethod; 29 | import org.springframework.http.MediaType; 30 | import org.springframework.test.web.client.MockRestServiceServer; 31 | import org.springframework.test.web.client.match.MockRestRequestMatchers; 32 | import org.springframework.test.web.client.response.MockRestResponseCreators; 33 | import org.springframework.web.client.RestTemplate; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | 37 | /** 38 | * Tests for {@link MavenMetadataVersionResolver}. 39 | * 40 | * @author Andy Wilkinson 41 | */ 42 | public class MavenMetadataVersionResolverTests { 43 | 44 | @Test 45 | public void versionsAreResolvedFromMavenMetadata() { 46 | RestTemplate rest = new RestTemplate(); 47 | MockRestServiceServer server = MockRestServiceServer.bindTo(rest).build(); 48 | server.expect(MockRestRequestMatchers 49 | .requestTo("https://repo.example.com/maven2/org/springframework/spring-core/maven-metadata.xml")) 50 | .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) 51 | .andRespond(MockRestResponseCreators.withSuccess( 52 | new FileSystemResource(new File("src/test/resources/spring-core-maven-metadata.xml")), 53 | MediaType.TEXT_XML)); 54 | Set versions = new MavenMetadataVersionResolver(rest, 55 | Arrays.asList("https://repo.example.com/maven2/")) 56 | .resolveVersions(new Module("org.springframework", "spring-core")); 57 | assertThat(versions.stream().map(DependencyVersion::toString).collect(Collectors.toList())).containsExactly( 58 | "4.3.0.RELEASE", "4.3.1.RELEASE", "4.3.2.RELEASE", "4.3.3.RELEASE", "4.3.4.RELEASE", "4.3.5.RELEASE", 59 | "4.3.6.RELEASE", "4.3.7.RELEASE", "4.3.8.RELEASE", "4.3.9.RELEASE", "4.3.10.RELEASE", "4.3.11.RELEASE", 60 | "5.0.0.RELEASE"); 61 | } 62 | 63 | @Test 64 | public void versionsFromMultipleRepositoriesAreCombined() { 65 | RestTemplate rest = new RestTemplate(); 66 | MockRestServiceServer server = MockRestServiceServer.bindTo(rest).build(); 67 | server.expect( 68 | MockRestRequestMatchers.requestTo("https://repo1.example.com/com/example/core/maven-metadata.xml")) 69 | .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) 70 | .andRespond(MockRestResponseCreators.withSuccess( 71 | new FileSystemResource(new File("src/test/resources/repo1-maven-metadata.xml")), 72 | MediaType.TEXT_XML)); 73 | server.expect( 74 | MockRestRequestMatchers.requestTo("https://repo2.example.com/com/example/core/maven-metadata.xml")) 75 | .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) 76 | .andRespond(MockRestResponseCreators.withSuccess( 77 | new FileSystemResource(new File("src/test/resources/repo2-maven-metadata.xml")), 78 | MediaType.TEXT_XML)); 79 | Set versions = new MavenMetadataVersionResolver(rest, 80 | Arrays.asList("https://repo1.example.com", "https://repo2.example.com")) 81 | .resolveVersions(new Module("com.example", "core")); 82 | assertThat(versions.stream().map(DependencyVersion::toString).collect(Collectors.toList())) 83 | .containsExactly("1.0.0.RELEASE", "1.1.0.RELEASE"); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/UpgradePolicyTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade; 18 | 19 | import io.spring.bomr.upgrade.version.DependencyVersion; 20 | import org.eclipse.aether.version.InvalidVersionSpecificationException; 21 | import org.junit.Test; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | /** 26 | * Tests for {@link UpgradePolicy}. 27 | * 28 | * @author Andy Wilkinson 29 | */ 30 | public class UpgradePolicyTests { 31 | 32 | @Test 33 | public void anyWhenCandidateIsNewerMajorThanCurrentShouldReturnTrue() throws InvalidVersionSpecificationException { 34 | assertThat(UpgradePolicy.ANY.test(version("2.0.0"), version("1.0.0"))).isTrue(); 35 | } 36 | 37 | @Test 38 | public void anyWhenCandidateIsNewerMinorThanCurrentShouldReturnTrue() throws InvalidVersionSpecificationException { 39 | assertThat(UpgradePolicy.ANY.test(version("1.1.0"), version("1.0.0"))).isTrue(); 40 | } 41 | 42 | @Test 43 | public void anyWhenCandidateIsNewerPatchThanCurrentShouldReturnTrue() throws InvalidVersionSpecificationException { 44 | assertThat(UpgradePolicy.ANY.test(version("1.0.1"), version("1.0.0"))).isTrue(); 45 | } 46 | 47 | @Test 48 | public void anyWhenCandidateIsSameAsCurrentShouldReturnFalse() throws InvalidVersionSpecificationException { 49 | assertThat(UpgradePolicy.ANY.test(version("1.0.0"), version("1.0.0"))).isFalse(); 50 | } 51 | 52 | @Test 53 | public void anyWhenCandidateIsOlderThanCurrentShouldReturnFalse() throws InvalidVersionSpecificationException { 54 | assertThat(UpgradePolicy.ANY.test(version("2.0.0"), version("2.0.1"))).isFalse(); 55 | } 56 | 57 | @Test 58 | public void sameMajorVersionWhenCandidateIsNewerMajorThanCurrentShouldReturnFalse() 59 | throws InvalidVersionSpecificationException { 60 | assertThat(UpgradePolicy.SAME_MAJOR_VERSION.test(version("2.0.0"), version("1.0.0"))).isFalse(); 61 | } 62 | 63 | @Test 64 | public void sameMajorVersionWhenCandidateIsNewerMinorThanCurrentShouldReturnTrue() 65 | throws InvalidVersionSpecificationException { 66 | assertThat(UpgradePolicy.SAME_MAJOR_VERSION.test(version("1.1.0"), version("1.0.0"))).isTrue(); 67 | } 68 | 69 | @Test 70 | public void sameMajorVersionWhenCandidateIsNewerPatchThanCurrentShouldReturnTrue() 71 | throws InvalidVersionSpecificationException { 72 | assertThat(UpgradePolicy.SAME_MAJOR_VERSION.test(version("1.0.1"), version("1.0.0"))).isTrue(); 73 | } 74 | 75 | @Test 76 | public void sameMajorVersionWhenCandidateIsSameAsCurrentShouldReturnFalse() 77 | throws InvalidVersionSpecificationException { 78 | assertThat(UpgradePolicy.SAME_MAJOR_VERSION.test(version("1.0.0"), version("1.0.0"))).isFalse(); 79 | } 80 | 81 | @Test 82 | public void sameMajorVersionWhenCandidateIsOlderThanCurrentShouldReturnFalse() 83 | throws InvalidVersionSpecificationException { 84 | assertThat(UpgradePolicy.SAME_MAJOR_VERSION.test(version("2.0.0"), version("2.1.0"))).isFalse(); 85 | } 86 | 87 | @Test 88 | public void sameMinorVersionWhenCandidateIsNewerMajorThanCurrentShouldReturnFalse() 89 | throws InvalidVersionSpecificationException { 90 | assertThat(UpgradePolicy.SAME_MINOR_VERSION.test(version("2.0.0"), version("1.0.0"))).isFalse(); 91 | } 92 | 93 | @Test 94 | public void sameMinorVersionWhenCandidateIsNewerMinorThanCurrentShouldReturnFalse() 95 | throws InvalidVersionSpecificationException { 96 | assertThat(UpgradePolicy.SAME_MINOR_VERSION.test(version("10.13.1"), version("10.14.1"))).isFalse(); 97 | } 98 | 99 | @Test 100 | public void sameMinorVersionWhenCandidateIsNewerPatchThanCurrentShouldReturnTrue() 101 | throws InvalidVersionSpecificationException { 102 | assertThat(UpgradePolicy.SAME_MINOR_VERSION.test(version("1.0.1"), version("1.0.0"))).isTrue(); 103 | } 104 | 105 | @Test 106 | public void sameMinorVersionWhenCandidateIsSameAsCurrentShouldReturnFalse() 107 | throws InvalidVersionSpecificationException { 108 | assertThat(UpgradePolicy.SAME_MINOR_VERSION.test(version("1.0.0"), version("1.0.0"))).isFalse(); 109 | } 110 | 111 | @Test 112 | public void sameMinorVersionWhenCandidateIsOlderThanCurrentShouldReturnFalse() 113 | throws InvalidVersionSpecificationException { 114 | assertThat(UpgradePolicy.SAME_MINOR_VERSION.test(version("2.1.0"), version("2.1.1"))).isFalse(); 115 | } 116 | 117 | private DependencyVersion version(String version) { 118 | return DependencyVersion.parse(version); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/version/ArtifactVersionDependencyVersionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * Tests for {@link ArtifactVersionDependencyVersion}. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public class ArtifactVersionDependencyVersionTests { 29 | 30 | @Test 31 | public void parseWhenVersionIsNotAMavenVersionShouldReturnNull() { 32 | assertThat(version("1.2.3.1")).isNull(); 33 | } 34 | 35 | @Test 36 | public void parseWhenVersionIsAMavenVersionShouldReturnAVersion() { 37 | assertThat(version("1.2.3")).isNotNull(); 38 | } 39 | 40 | @Test 41 | public void isNewerThanWhenInputIsOlderMajorShouldReturnTrue() { 42 | assertThat(version("2.1.2").isNewerThan(version("1.9.0"))).isTrue(); 43 | } 44 | 45 | @Test 46 | public void isNewerThanWhenInputIsOlderMinorShouldReturnTrue() { 47 | assertThat(version("2.1.2").isNewerThan(version("2.0.2"))).isTrue(); 48 | } 49 | 50 | @Test 51 | public void isNewerThanWhenInputIsOlderPatchShouldReturnTrue() { 52 | assertThat(version("2.1.2").isNewerThan(version("2.1.1"))).isTrue(); 53 | } 54 | 55 | @Test 56 | public void isNewerThanWhenInputIsNewerMajorShouldReturnFalse() { 57 | assertThat(version("2.1.2").isNewerThan(version("3.2.1"))).isFalse(); 58 | } 59 | 60 | @Test 61 | public void isSameMajorAndNewerThanWhenMinorIsOlderShouldReturnTrue() { 62 | assertThat(version("1.10.2").isSameMajorAndNewerThan(version("1.9.0"))).isTrue(); 63 | } 64 | 65 | @Test 66 | public void isSameMajorAndNewerThanWhenMajorIsOlderShouldReturnFalse() { 67 | assertThat(version("2.0.2").isSameMajorAndNewerThan(version("1.9.0"))).isFalse(); 68 | } 69 | 70 | @Test 71 | public void isSameMajorAndNewerThanWhenPatchIsNewerShouldReturnTrue() { 72 | assertThat(version("2.1.2").isSameMajorAndNewerThan(version("2.1.1"))).isTrue(); 73 | } 74 | 75 | @Test 76 | public void isSameMajorAndNewerThanWhenMinorIsNewerShouldReturnFalse() { 77 | assertThat(version("2.1.2").isSameMajorAndNewerThan(version("2.2.1"))).isFalse(); 78 | } 79 | 80 | @Test 81 | public void isSameMajorAndNewerThanWhenMajorIsNewerShouldReturnFalse() { 82 | assertThat(version("2.1.2").isSameMajorAndNewerThan(version("3.0.1"))).isFalse(); 83 | } 84 | 85 | @Test 86 | public void isSameMinorAndNewerThanWhenPatchIsOlderShouldReturnTrue() { 87 | assertThat(version("1.10.2").isSameMinorAndNewerThan(version("1.10.1"))).isTrue(); 88 | } 89 | 90 | @Test 91 | public void isSameMinorAndNewerThanWhenMinorIsOlderShouldReturnFalse() { 92 | assertThat(version("2.1.2").isSameMinorAndNewerThan(version("2.0.1"))).isFalse(); 93 | } 94 | 95 | @Test 96 | public void isSameMinorAndNewerThanWhenVersionsAreTheSameShouldReturnFalse() { 97 | assertThat(version("2.1.2").isSameMinorAndNewerThan(version("2.1.2"))).isFalse(); 98 | } 99 | 100 | @Test 101 | public void isSameMinorAndNewerThanWhenPatchIsNewerShouldReturnFalse() { 102 | assertThat(version("2.1.2").isSameMinorAndNewerThan(version("2.1.3"))).isFalse(); 103 | } 104 | 105 | @Test 106 | public void isSameMinorAndNewerThanWhenMinorIsNewerShouldReturnFalse() { 107 | assertThat(version("2.1.2").isSameMinorAndNewerThan(version("2.0.1"))).isFalse(); 108 | } 109 | 110 | @Test 111 | public void isSameMinorAndNewerThanWhenMajorIsNewerShouldReturnFalse() { 112 | assertThat(version("3.1.2").isSameMinorAndNewerThan(version("2.0.1"))).isFalse(); 113 | } 114 | 115 | private ArtifactVersionDependencyVersion version(String version) { 116 | return ArtifactVersionDependencyVersion.parse(version); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/version/DependencyVersionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * Tests for {@link DependencyVersion}. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public class DependencyVersionTests { 29 | 30 | @Test 31 | public void parseWhenValidMavenVersionShouldReturnArtifactVersionDependencyVersion() { 32 | assertThat(DependencyVersion.parse("1.2.3.Final")).isInstanceOf(ArtifactVersionDependencyVersion.class); 33 | } 34 | 35 | @Test 36 | public void parseWhenReleaseTrainShouldReturnReleaseTrainDependencyVersion() { 37 | assertThat(DependencyVersion.parse("Ingalls-SR5")).isInstanceOf(ReleaseTrainDependencyVersion.class); 38 | } 39 | 40 | @Test 41 | public void parseWhenMavenLikeVersionWithNumericQualifieShouldReturnNumericQualifierDependencyVersion() { 42 | assertThat(DependencyVersion.parse("1.2.3.4")).isInstanceOf(NumericQualifierDependencyVersion.class); 43 | } 44 | 45 | @Test 46 | public void parseWhenVersionWithLeadingZeroesShouldReturnLeadingZeroesDependencyVersion() { 47 | assertThat(DependencyVersion.parse("1.4.01")).isInstanceOf(LeadingZeroesDependencyVersion.class); 48 | } 49 | 50 | @Test 51 | public void parseWhenVersionWithCombinedPatchAndQualifierShouldReturnCombinedPatchAndQualifierDependencyVersion() { 52 | assertThat(DependencyVersion.parse("4.0.0M4")).isInstanceOf(CombinedPatchAndQualifierDependencyVersion.class); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/version/NumericQualifierDependencyVersionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * Tests for {@link NumericQualifierDependencyVersion}. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public class NumericQualifierDependencyVersionTests { 29 | 30 | @Test 31 | public void isNewerThanOnVersionWithNumericQualifierWhenInputHasNoQualifierShouldReturnTrue() { 32 | assertThat(version("2.9.9.20190806").isNewerThan(DependencyVersion.parse("2.9.9"))).isTrue(); 33 | } 34 | 35 | @Test 36 | public void isNewerThanOnVersionWithNumericQualifierWhenInputHasOlderQualifierShouldReturnTrue() { 37 | assertThat(version("2.9.9.20190806").isNewerThan(version("2.9.9.20190805"))).isTrue(); 38 | } 39 | 40 | @Test 41 | public void isNewerThanOnVersionWithNumericQualifierWhenInputHasNewerQualifierShouldReturnFalse() { 42 | assertThat(version("2.9.9.20190806").isNewerThan(version("2.9.9.20190807"))).isFalse(); 43 | } 44 | 45 | @Test 46 | public void isNewerThanOnVersionWithNumericQualifierWhenInputHasSameQualifierShouldReturnFalse() { 47 | assertThat(version("2.9.9.20190806").isNewerThan(version("2.9.9.20190806"))).isFalse(); 48 | } 49 | 50 | private NumericQualifierDependencyVersion version(String version) { 51 | return NumericQualifierDependencyVersion.parse(version); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/io/spring/bomr/upgrade/version/ReleaseTrainDependencyVersionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.spring.bomr.upgrade.version; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * Tests for {@link ReleaseTrainDependencyVersion}. 25 | * 26 | * @author Andy Wilkinson 27 | */ 28 | public class ReleaseTrainDependencyVersionTests { 29 | 30 | @Test 31 | public void parsingOfANonReleaseTrainVersionReturnsNull() { 32 | assertThat(version("5.1.4.RELEASE")).isNull(); 33 | } 34 | 35 | @Test 36 | public void parsingOfAReleaseTrainVersionReturnsVersion() { 37 | assertThat(version("Lovelace-SR3")).isNotNull(); 38 | } 39 | 40 | @Test 41 | public void isNewerThanWhenReleaseTrainIsNewerShouldReturnTrue() { 42 | assertThat(version("Lovelace-RELEASE").isNewerThan(version("Kay-SR5"))).isTrue(); 43 | } 44 | 45 | @Test 46 | public void isNewerThanWhenVersionIsNewerShouldReturnTrue() { 47 | assertThat(version("Kay-SR10").isNewerThan(version("Kay-SR5"))).isTrue(); 48 | } 49 | 50 | @Test 51 | public void isNewerThanWhenVersionIsOlderShouldReturnFalse() { 52 | assertThat(version("Kay-RELEASE").isNewerThan(version("Kay-SR5"))).isFalse(); 53 | } 54 | 55 | @Test 56 | public void isNewerThanWhenReleaseTrainIsOlderShouldReturnFalse() { 57 | assertThat(version("Ingalls-RELEASE").isNewerThan(version("Kay-SR5"))).isFalse(); 58 | } 59 | 60 | @Test 61 | public void isSameMajorAndNewerWhenWhenReleaseTrainIsNewerShouldReturnTrue() { 62 | assertThat(version("Lovelace-RELEASE").isSameMajorAndNewerThan(version("Kay-SR5"))).isTrue(); 63 | } 64 | 65 | @Test 66 | public void isSameMajorAndNewerThanWhenReleaseTrainIsOlderShouldReturnFalse() { 67 | assertThat(version("Ingalls-RELEASE").isSameMajorAndNewerThan(version("Kay-SR5"))).isFalse(); 68 | } 69 | 70 | @Test 71 | public void isSameMajorAndNewerThanWhenVersionIsNewerShouldReturnTrue() { 72 | assertThat(version("Kay-SR6").isSameMajorAndNewerThan(version("Kay-SR5"))).isTrue(); 73 | } 74 | 75 | @Test 76 | public void isSameMinorAndNewerThanWhenReleaseTrainIsNewerShouldReturnFalse() { 77 | assertThat(version("Lovelace-RELEASE").isSameMinorAndNewerThan(version("Kay-SR5"))).isFalse(); 78 | } 79 | 80 | @Test 81 | public void isSameMinorAndNewerThanWhenReleaseTrainIsTheSameAndVersionIsNewerShouldReturnTrue() { 82 | assertThat(version("Kay-SR6").isSameMinorAndNewerThan(version("Kay-SR5"))).isTrue(); 83 | } 84 | 85 | @Test 86 | public void isSameMinorAndNewerThanWhenReleaseTrainAndVersionAreTheSameShouldReturnFalse() { 87 | assertThat(version("Kay-SR6").isSameMinorAndNewerThan(version("Kay-SR6"))).isFalse(); 88 | } 89 | 90 | @Test 91 | public void isSameMinorAndNewerThanWhenReleaseTrainIsTheSameAndVersionIsOlderShouldReturnFalse() { 92 | assertThat(version("Kay-SR6").isSameMinorAndNewerThan(version("Kay-SR7"))).isFalse(); 93 | } 94 | 95 | @Test 96 | public void whenComparedWithADifferentDependencyVersionTypeThenTheResultsAreNonZero() { 97 | ReleaseTrainDependencyVersion dysprosium = ReleaseTrainDependencyVersion.parse("Dysprosium-SR16"); 98 | ArtifactVersionDependencyVersion twentyTwenty = ArtifactVersionDependencyVersion.parse("2020.0.0"); 99 | assertThat(dysprosium.compareTo(twentyTwenty)).isLessThan(0); 100 | assertThat(twentyTwenty.compareTo(dysprosium)).isGreaterThan(0); 101 | } 102 | 103 | private static ReleaseTrainDependencyVersion version(String input) { 104 | return ReleaseTrainDependencyVersion.parse(input); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/infinispan/page6.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "docs": [ 4 | { 5 | "a": "infinispan-server-core", 6 | "ec": [ 7 | "-sources.jar", 8 | "-test-sources.jar", 9 | "-tests.jar", 10 | ".jar", 11 | ".pom" 12 | ], 13 | "g": "org.infinispan", 14 | "id": "org.infinispan:infinispan-server-core:9.4.15.Final", 15 | "p": "bundle", 16 | "tags": [ 17 | "infinispan", 18 | "server", 19 | "core", 20 | "components" 21 | ], 22 | "timestamp": 1560795545000, 23 | "v": "9.4.15.Final" 24 | }, 25 | { 26 | "a": "infinispan-spring5-common", 27 | "ec": [ 28 | "-sources.jar", 29 | "-test-sources.jar", 30 | ".jar", 31 | "-tests.jar", 32 | ".pom" 33 | ], 34 | "g": "org.infinispan", 35 | "id": "org.infinispan:infinispan-spring5-common:9.4.15.Final", 36 | "p": "jar", 37 | "tags": [ 38 | "distributed", 39 | "used", 40 | "same", 41 | "springframework", 42 | "namespace", 43 | "accesses", 44 | "over", 45 | "primary", 46 | "features", 47 | "facilitating", 48 | "factorybeans", 49 | "central", 50 | "support", 51 | "defined", 52 | "offers", 53 | "definitions", 54 | "project", 55 | "powered", 56 | "infinispan", 57 | "abstraction", 58 | "backed", 59 | "components", 60 | "outside", 61 | "creation", 62 | "remotecachemanager", 63 | "cachemanager", 64 | "remotely", 65 | "from", 66 | "running", 67 | "spring", 68 | "embeddedcachemanager", 69 | "network", 70 | "shortcut", 71 | "allowing", 72 | "integration", 73 | "performance", 74 | "above", 75 | "various", 76 | "colocated", 77 | "jndi", 78 | "retrieved", 79 | "caching", 80 | "classes", 81 | "application", 82 | "cache", 83 | "needs", 84 | "your", 85 | "provides", 86 | "addition", 87 | "access", 88 | "cachecontainer", 89 | "reference", 90 | "implementation", 91 | "context", 92 | "core", 93 | "within", 94 | "high" 95 | ], 96 | "timestamp": 1560795538000, 97 | "v": "9.4.15.Final" 98 | }, 99 | { 100 | "a": "infinispan-cdi-remote", 101 | "ec": [ 102 | "-sources.jar", 103 | "-test-sources.jar", 104 | "-tests.jar", 105 | ".jar", 106 | ".pom" 107 | ], 108 | "g": "org.infinispan", 109 | "id": "org.infinispan:infinispan-cdi-remote:9.4.15.Final", 110 | "p": "bundle", 111 | "tags": [ 112 | "module", 113 | "infinispan", 114 | "common", 115 | "parent" 116 | ], 117 | "timestamp": 1560795535000, 118 | "v": "9.4.15.Final" 119 | } 120 | ], 121 | "numFound": 103, 122 | "start": 100 123 | }, 124 | "responseHeader": { 125 | "QTime": 0, 126 | "params": { 127 | "core": "", 128 | "fl": "id,g,a,v,p,ec,timestamp,tags", 129 | "indent": "off", 130 | "q": "g:org.infinispan AND v:9.4.15.Final", 131 | "rows": "20", 132 | "sort": "score desc,timestamp desc,g asc,a asc,v desc", 133 | "start": "100", 134 | "version": "2.2", 135 | "wt": "json" 136 | }, 137 | "status": 0 138 | } 139 | } -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler

17 |
18 |
19 |
20 |
21 | ../
22 | internal/                                                        -         -
23 | quartz/                                                          -         -
24 | quartz-backward-compat/                                          -         -
25 | quartz-commonj/                                                  -         -
26 | quartz-jboss/                                                    -         -
27 | quartz-jobs/                                                     -         -
28 | quartz-oracle/                                                   -         -
29 | quartz-parent/                                                   -         -
30 | quartz-weblogic/                                                 -         -
31 | 		
32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/internal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 302 Moved Temporarily 3 | 4 |

302 Moved Temporarily

5 |
    6 |
  • Code: Found
  • 7 |
  • Message: Resource Found
  • 8 |
  • RequestId: E58ACE82DBB1ED1E
  • 9 |
  • HostId: R6jZCOY1+UtVUsRIbxKCogNKwHyS1y3FS8HGW0td0qn1Aob6ZMfcOmphE2z7ogBy1IWCUEbhI08=
  • 10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-backward-compat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-backward-compat 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-backward-compat

17 |
18 |
19 |
20 |
21 | ../
22 | 2.0.0/                                            2011-03-28 20:34         -      
23 | 2.0.1/                                            2011-04-14 03:39         -      
24 | 2.0.2/                                            2011-07-07 18:47         -      
25 | 2.1.0/                                            2011-09-22 21:48         -      
26 | 2.1.1/                                            2011-11-14 20:21         -      
27 | 2.1.2/                                            2011-12-20 13:56         -      
28 | 2.1.3/                                            2012-01-30 19:31         -      
29 | 2.1.4/                                            2012-04-17 19:23         -      
30 | 2.1.5/                                            2012-04-27 14:51         -      
31 | 2.1.6/                                            2013-02-22 21:20         -      
32 | 2.1.7/                                            2013-03-05 15:26         -      
33 | maven-metadata.xml                                2013-03-05 15:39       659      
34 | maven-metadata.xml.md5                            2013-03-05 15:39        32      
35 | maven-metadata.xml.sha1                           2013-03-05 15:39        40      
36 | 		
37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-commonj/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-commonj 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-commonj

17 |
18 |
19 |
20 |
21 | ../
22 | 1.8.6/                                            2012-01-12 21:44         -      
23 | 2.1.1/                                            2011-11-14 20:22         -      
24 | 2.1.2/                                            2011-12-20 13:57         -      
25 | 2.1.3/                                            2012-01-30 19:31         -      
26 | 2.1.4/                                            2012-04-17 19:23         -      
27 | 2.1.5/                                            2012-04-27 14:51         -      
28 | 2.1.6/                                            2013-02-22 21:19         -      
29 | 2.1.7/                                            2013-03-05 15:26         -      
30 | maven-metadata.xml                                2013-03-05 15:39       558      
31 | maven-metadata.xml.md5                            2013-03-05 15:39        32      
32 | maven-metadata.xml.sha1                           2013-03-05 15:39        40      
33 | 		
34 |
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-jboss/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-jboss 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-jboss

17 |
18 |
19 |
20 |
21 | ../
22 | 1.7.2/                                            2010-02-10 14:53         -      
23 | 1.7.3/                                            2010-02-24 18:47         -      
24 | 1.8.0/                                            2010-04-23 04:46         -      
25 | 1.8.1/                                            2010-06-11 21:10         -      
26 | 1.8.2/                                            2010-06-17 23:56         -      
27 | 1.8.3/                                            2010-06-22 21:10         -      
28 | 1.8.4/                                            2010-07-19 23:03         -      
29 | 1.8.5/                                            2011-04-14 03:30         -      
30 | 1.8.6/                                            2012-01-12 21:43         -      
31 | 2.0.0/                                            2011-03-28 20:34         -      
32 | 2.0.1/                                            2011-04-14 03:39         -      
33 | 2.0.2/                                            2011-07-07 18:47         -      
34 | 2.1.0/                                            2011-09-22 21:47         -      
35 | 2.1.1/                                            2011-11-14 20:21         -      
36 | 2.1.2/                                            2011-12-20 13:56         -      
37 | 2.1.3/                                            2012-01-30 19:30         -      
38 | 2.1.4/                                            2012-04-17 19:22         -      
39 | 2.1.5/                                            2012-04-27 14:51         -      
40 | 2.1.6/                                            2013-02-22 21:16         -      
41 | 2.1.7/                                            2013-03-05 15:24         -      
42 | maven-metadata.xml                                2013-03-05 15:39       928      
43 | maven-metadata.xml.md5                            2013-03-05 15:39        32      
44 | maven-metadata.xml.sha1                           2013-03-05 15:39        40      
45 | 		
46 |
47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-jobs/2.3.0/quartz-jobs-2.3.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/bomr/91a916478d46d89ac803b9c37155d0fbba84407d/src/test/resources/artifacts/org/quartz-scheduler/quartz-jobs/2.3.0/quartz-jobs-2.3.0.jar -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-jobs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-jobs 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-jobs

17 |
18 |
19 |
20 |
21 | ../
22 | 2.2.0/                                            2013-06-29 21:04         -      
23 | 2.2.1/                                            2013-09-25 18:48         -      
24 | 2.2.2/                                            2015-10-12 11:52         -      
25 | 2.2.3/                                            2016-04-18 18:26         -      
26 | 2.3.0/                                            2017-04-19 19:41         -      
27 | maven-metadata.xml                                2017-04-19 20:16       462      
28 | maven-metadata.xml.md5                            2017-04-19 20:16        32      
29 | maven-metadata.xml.sha1                           2017-04-19 20:16        40      
30 | 		
31 |
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-oracle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-oracle 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-oracle

17 |
18 |
19 |
20 |
21 | ../
22 | 1.7.2/                                            2010-02-10 14:53         -      
23 | 1.8.0/                                            2010-04-23 04:46         -      
24 | 1.8.1/                                            2010-06-11 21:10         -      
25 | 1.8.2/                                            2010-06-17 23:57         -      
26 | 1.8.3/                                            2010-06-22 21:10         -      
27 | 1.8.4/                                            2010-07-19 23:04         -      
28 | 1.8.5/                                            2011-04-14 03:31         -      
29 | 1.8.6/                                            2012-01-12 21:43         -      
30 | 2.0.1/                                            2011-04-14 03:39         -      
31 | 2.0.2/                                            2011-07-07 18:48         -      
32 | 2.1.0/                                            2011-09-22 21:48         -      
33 | 2.1.1/                                            2011-11-14 20:22         -      
34 | 2.1.2/                                            2011-12-20 13:57         -      
35 | 2.1.3/                                            2012-01-30 19:31         -      
36 | 2.1.4/                                            2012-04-17 19:23         -      
37 | 2.1.5/                                            2012-04-27 14:51         -      
38 | 2.1.6/                                            2013-02-22 21:17         -      
39 | 2.1.7/                                            2013-03-05 15:25         -      
40 | maven-metadata.xml                                2013-03-05 15:39       867      
41 | maven-metadata.xml.md5                            2013-03-05 15:39        32      
42 | maven-metadata.xml.sha1                           2013-03-05 15:39        40      
43 | 		
44 |
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-parent/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-parent 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-parent

17 |
18 |
19 |
20 |
21 | ../
22 | 1.7.0/                                                           -         -      
23 | 1.7.2/                                            2010-02-10 14:52         -      
24 | 1.7.3/                                            2010-02-24 18:46         -      
25 | 1.8.0/                                            2010-04-23 04:45         -      
26 | 1.8.1/                                            2010-06-11 21:09         -      
27 | 1.8.2/                                            2010-06-17 23:55         -      
28 | 1.8.3/                                            2010-06-22 21:09         -      
29 | 1.8.4/                                            2010-07-19 23:01         -      
30 | 1.8.5/                                            2011-04-14 03:30         -      
31 | 1.8.6/                                            2012-01-12 21:43         -      
32 | 2.0.0/                                            2011-03-28 20:32         -      
33 | 2.0.1/                                            2011-04-14 03:38         -      
34 | 2.0.2/                                            2011-07-07 18:45         -      
35 | 2.1.0/                                            2011-09-22 21:46         -      
36 | 2.1.1/                                            2011-11-14 20:21         -      
37 | 2.1.2/                                            2011-12-20 13:53         -      
38 | 2.1.3/                                            2012-01-30 19:27         -      
39 | 2.1.4/                                            2012-04-17 19:21         -      
40 | 2.1.5/                                            2012-04-27 14:50         -      
41 | 2.1.6/                                            2013-02-22 21:12         -      
42 | 2.1.7/                                            2013-03-05 15:22         -      
43 | 2.2.0/                                            2013-06-29 21:02         -      
44 | 2.2.1/                                            2013-09-25 18:46         -      
45 | 2.2.2/                                            2015-10-12 11:51         -      
46 | 2.2.3/                                            2016-04-18 18:25         -      
47 | 2.3.0/                                            2017-04-19 19:40         -      
48 | maven-metadata.xml                                2017-04-19 20:16      1084      
49 | maven-metadata.xml.md5                            2017-04-19 20:16        32      
50 | maven-metadata.xml.sha1                           2017-04-19 20:16        40      
51 | 		
52 |
53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz-weblogic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz-weblogic 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz-weblogic

17 |
18 |
19 |
20 |
21 | ../
22 | 1.7.2/                                            2010-02-10 14:53         -      
23 | 1.8.0/                                            2010-04-23 04:46         -      
24 | 1.8.1/                                            2010-06-11 21:10         -      
25 | 1.8.2/                                            2010-06-17 23:57         -      
26 | 1.8.3/                                            2010-06-22 21:10         -      
27 | 1.8.4/                                            2010-07-19 23:04         -      
28 | 1.8.5/                                            2011-04-14 03:31         -      
29 | 1.8.6/                                            2012-01-12 21:43         -      
30 | 2.0.1/                                            2011-04-14 03:40         -      
31 | 2.0.2/                                            2011-07-07 18:48         -      
32 | 2.1.0/                                            2011-09-22 21:48         -      
33 | 2.1.1/                                            2011-11-14 20:22         -      
34 | 2.1.2/                                            2011-12-20 13:57         -      
35 | 2.1.3/                                            2012-01-30 19:31         -      
36 | 2.1.4/                                            2012-04-17 19:23         -      
37 | 2.1.5/                                            2012-04-27 14:51         -      
38 | 2.1.6/                                            2013-02-22 21:18         -      
39 | 2.1.7/                                            2013-03-05 15:25         -      
40 | maven-metadata.xml                                2013-03-05 15:39       869      
41 | maven-metadata.xml.md5                            2013-03-05 15:39        32      
42 | maven-metadata.xml.sha1                           2013-03-05 15:39        40      
43 | 		
44 |
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz/2.3.0/quartz-2.3.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/bomr/91a916478d46d89ac803b9c37155d0fbba84407d/src/test/resources/artifacts/org/quartz-scheduler/quartz/2.3.0/quartz-2.3.0.jar -------------------------------------------------------------------------------- /src/test/resources/artifacts/org/quartz-scheduler/quartz/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: org/quartz-scheduler/quartz 6 | 7 | 12 | 13 | 14 | 15 |
16 |

org/quartz-scheduler/quartz

17 |
18 |
19 |
20 |
21 | ../
22 | 1.7.2/                                            2010-02-10 14:53         -      
23 | 1.7.3/                                            2010-02-24 18:47         -      
24 | 1.8.0/                                            2010-04-23 04:45         -      
25 | 1.8.1/                                            2010-06-11 21:10         -      
26 | 1.8.2/                                            2010-06-17 23:56         -      
27 | 1.8.3/                                            2010-06-22 21:09         -      
28 | 1.8.4/                                            2010-07-19 23:03         -      
29 | 1.8.5/                                            2011-04-14 03:30         -      
30 | 1.8.6/                                            2012-01-12 21:43         -      
31 | 2.0.0/                                            2011-03-28 20:33         -      
32 | 2.0.1/                                            2011-04-14 03:39         -      
33 | 2.0.2/                                            2011-07-07 18:47         -      
34 | 2.1.0/                                            2011-09-22 21:47         -      
35 | 2.1.1/                                            2011-11-14 20:21         -      
36 | 2.1.2/                                            2011-12-20 13:56         -      
37 | 2.1.3/                                            2012-01-30 19:30         -      
38 | 2.1.4/                                            2012-04-17 19:22         -      
39 | 2.1.5/                                            2012-04-27 14:50         -      
40 | 2.1.6/                                            2013-02-22 21:15         -      
41 | 2.1.7/                                            2013-03-05 15:24         -      
42 | 2.2.0/                                            2013-06-29 21:06         -      
43 | 2.2.1/                                            2013-09-25 18:50         -      
44 | 2.2.2/                                            2015-10-12 11:52         -      
45 | 2.2.3/                                            2016-04-18 18:27         -      
46 | 2.3.0/                                            2017-04-19 19:41         -      
47 | maven-metadata.xml                                2017-04-19 20:16      1077      
48 | maven-metadata.xml.md5                            2017-04-19 20:16        32      
49 | maven-metadata.xml.sha1                           2017-04-19 20:16        40      
50 | 		
51 |
52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /src/test/resources/repo1-maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.example 4 | core 5 | 6 | 1.0.0.RELEASE 7 | 1.0.0.RELEASE 8 | 9 | 1.0.0.RELEASE 10 | 11 | 20170928121756 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/resources/repo2-maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.example 4 | core 5 | 6 | 1.1.0.RELEASE 7 | 1.1.0.RELEASE 8 | 9 | 1.0.0.RELEASE 10 | 1.1.0.RELEASE 11 | 12 | 20170928121756 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/resources/spring-core-maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.springframework 4 | spring-core 5 | 6 | 5.0.0.RELEASE 7 | 5.0.0.RELEASE 8 | 9 | 4.3.0.RELEASE 10 | 4.3.1.RELEASE 11 | 4.3.2.RELEASE 12 | 4.3.3.RELEASE 13 | 4.3.4.RELEASE 14 | 4.3.5.RELEASE 15 | 4.3.6.RELEASE 16 | 4.3.7.RELEASE 17 | 4.3.8.RELEASE 18 | 4.3.9.RELEASE 19 | 4.3.10.RELEASE 20 | 4.3.11.RELEASE 21 | 5.0.0.RELEASE 22 | 23 | 20170928121756 24 | 25 | 26 | --------------------------------------------------------------------------------