diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..5c35341eb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +# Unix-style linebreaks with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +# space indentation for Java +[*.java] +indent_size = 4 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..3c0f4c376 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly +- package-ecosystem: maven + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05b389dac..01cfa5509 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,13 +12,13 @@ jobs: if: github.repository == 'pgjdbc/r2dbc-postgresql' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 1.8 - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 8 - distribution: temurin - cache: maven + java-version: '17' + distribution: 'temurin' + cache: 'maven' - name: Build with Maven env: SONATYPE_USER: ${{ secrets.SONATYPE_USER }} diff --git a/.github/workflows/pullrequests.yml b/.github/workflows/pullrequests.yml index d48e10976..aba1ed0af 100644 --- a/.github/workflows/pullrequests.yml +++ b/.github/workflows/pullrequests.yml @@ -9,12 +9,12 @@ jobs: pr-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 1.8 - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 8 - distribution: temurin - cache: maven + java-version: '17' + distribution: 'temurin' + cache: 'maven' - name: Build with Maven run: ./mvnw -B verify -D skipITs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2545e1d50..fc49cd238 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,14 +12,14 @@ jobs: if: github.repository == 'pgjdbc/r2dbc-postgresql' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 1.8 - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 8 - distribution: temurin + java-version: '17' + distribution: 'temurin' - name: Initialize Maven Version - run: ./mvnw -q org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version + run: ./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout - name: GPG Check run: gpg -k - name: Release with Maven diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index c32394f14..000000000 --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.5"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index 0d5e64988..7967f30dd 100644 Binary files a/.mvn/wrapper/maven-wrapper.jar and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 471b1a1c9..76e6ae113 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,20 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar diff --git a/ci/build-and-deploy-to-maven-central.sh b/ci/build-and-deploy-to-maven-central.sh index 095c3d9ea..0886285e6 100755 --- a/ci/build-and-deploy-to-maven-central.sh +++ b/ci/build-and-deploy-to-maven-central.sh @@ -2,7 +2,7 @@ set -euo pipefail -VERSION=$(./mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -o | grep -v INFO) +VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) if [[ $VERSION =~ [^.*-SNAPSHOT$] ]] ; then @@ -36,4 +36,3 @@ else echo "Not a release: $VERSION" exit 1 fi - diff --git a/mvnw b/mvnw index d2f0ea380..5e9618cac 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script +# Apache Maven Wrapper startup batch script, version 3.3.2 # # Required ENV vars: # ------------------ @@ -27,284 +27,306 @@ # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 # MAVEN_SKIP_RC - flag to disable loading of mavenrc files # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then +if [ -z "$MAVEN_SKIP_RC" ]; then - if [ -f /etc/mavenrc ] ; then + if [ -f /usr/local/etc/mavenrc ]; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ]; then . /etc/mavenrc fi - if [ -f "$HOME/.mavenrc" ] ; then + if [ -f "$HOME/.mavenrc" ]; then . "$HOME/.mavenrc" fi fi # OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; +cygwin=false +darwin=false mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi +case "$(uname)" in +CYGWIN*) cygwin=true ;; +MINGW*) mingw=true ;; +Darwin*) + darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)" + export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home" + export JAVA_HOME fi - ;; + fi + ;; esac -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` +if [ -z "$JAVA_HOME" ]; then + if [ -r /etc/gentoo-release ]; then + JAVA_HOME=$(java-config --jre-home) fi fi -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - # For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +if $cygwin; then + [ -n "$JAVA_HOME" ] \ + && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] \ + && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +if $mingw; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ + && JAVA_HOME="$( + cd "$JAVA_HOME" || ( + echo "cannot cd into $JAVA_HOME." >&2 + exit 1 + ) + pwd + )" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin; then + javaHome="$(dirname "$javaExecutable")" + javaExecutable="$(cd "$javaHome" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "$javaExecutable")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "$javaExecutable")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi fi fi -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then +if [ -z "$JAVACMD" ]; then + if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`which java`" + JAVACMD="$( + \unset -f command 2>/dev/null + \command -v java + )" fi fi -if [ ! -x "$JAVACMD" ] ; then +if [ ! -x "$JAVACMD" ]; then echo "Error: JAVA_HOME is not defined correctly." >&2 echo " We cannot execute $JAVACMD" >&2 exit 1 fi -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." +if [ -z "$JAVA_HOME" ]; then + echo "Warning: JAVA_HOME environment variable is not set." >&2 fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" + if [ -z "$1" ]; then + echo "Path not specified to find_maven_basedir" >&2 return 1 fi basedir="$1" wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then + while [ "$wdir" != '/' ]; do + if [ -d "$wdir"/.mvn ]; then basedir=$wdir break fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$( + cd "$wdir/.." || exit 1 + pwd + ) fi # end of workaround done - echo "${basedir}" + printf '%s' "$( + cd "$basedir" || exit 1 + pwd + )" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' <"$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" fi } -BASE_DIR=`find_maven_basedir "$(pwd)"` +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then - exit 1; + exit 1 fi +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in wrapperUrl) + wrapperUrl="$safeValue" + break + ;; + esac + done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget >/dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" + elif command -v curl >/dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi fi + fi fi ########################################################################################## # End of extension ########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in wrapperSha256Sum) + wrapperSha256Sum=$value + break + ;; + esac +done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum >/dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + [ -n "$JAVA_HOME" ] \ + && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] \ + && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] \ + && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd index b26ab24f0..4136715f0 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,15 +18,14 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script +@REM Apache Maven Wrapper startup batch script, version 3.3.2 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @REM @REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -46,8 +45,8 @@ if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") @REM Execute a user defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* :skipRcPre @setlocal @@ -60,22 +59,22 @@ set ERROR_CODE=0 @REM ==== START VALIDATION ==== if not "%JAVA_HOME%" == "" goto OkJHome -echo. +echo. >&2 echo Error: JAVA_HOME not found in your environment. >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 -echo. +echo. >&2 goto error :OkJHome if exist "%JAVA_HOME%\bin\java.exe" goto init -echo. +echo. >&2 echo Error: JAVA_HOME is set to an invalid directory. >&2 echo JAVA_HOME = "%JAVA_HOME%" >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 -echo. +echo. >&2 goto error @REM ==== END VALIDATION ==== @@ -120,10 +119,10 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @@ -134,11 +133,11 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% + echo Downloading from: %WRAPPER_URL% ) powershell -Command "&{"^ @@ -146,7 +145,7 @@ if exist %WRAPPER_JAR% ( "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ "}" if "%MVNW_VERBOSE%" == "true" ( echo Finished downloading %WRAPPER_JAR% @@ -154,11 +153,36 @@ if exist %WRAPPER_JAR% ( ) @REM End of extension +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end @@ -168,15 +192,15 @@ set ERROR_CODE=1 :end @endlocal & set ERROR_CODE=%ERROR_CODE% -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost @REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" :skipRcPost @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause +if "%MAVEN_BATCH_PAUSE%"=="on" pause -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% -exit /B %ERROR_CODE% +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 9b4f26ac4..68c8763a9 100644 --- a/pom.xml +++ b/pom.xml @@ -32,26 +32,39 @@ https://github.com/pgjdbc/r2dbc-postgresql - 3.25.3 - 4.2.0 - 4.0.3 - 1.8 + 3.26.0 + 4.2.1 + 5.1.0 + 8 3.0.2 - 5.10.2 - 1.35 + 5.10.3 + 1.37 0.3.0.RELEASE - 1.3.14 - 4.11.0 - 4.1.104.Final - 42.7.2 + 5.12.0 + 4.1.111.Final + 42.7.3 UTF-8 UTF-8 1.0.0.RELEASE - 2022.0.16 - 3.0 - 5.3.32 - 1.19.5 + 2023.0.7 + 3.1 + 2.0.13 + 6.1.10 + 1.19.8 1.19.0 + 3.6.0 + 3.3.0 + 1.6.0 + 3.13.0 + 3.1.2 + 3.5.0 + 3.3.0 + 3.2.4 + 3.4.2 + 3.7.0 + 3.3.1 + 3.3.0 + 1.6.13 @@ -116,6 +129,13 @@ pom import + + org.slf4j + slf4j-bom + ${slf4j.version} + pom + import + @@ -152,7 +172,13 @@ io.netty netty-transport-native-kqueue - osx-x86_64 + osx-aarch_64 + true + + + io.netty + netty-resolver-dns-native-macos + osx-aarch_64 true @@ -194,17 +220,7 @@ org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.junit.jupiter - junit-jupiter-engine + junit-jupiter test @@ -237,15 +253,35 @@ + + org.testcontainers + testcontainers + test + + + org.testcontainers + junit-jupiter + test + + + junit + junit + + + org.testcontainers postgresql test - ch.qos.logback - logback-classic - ${logback.version} + org.slf4j + slf4j-api + test + + + org.slf4j + slf4j-nop test @@ -261,7 +297,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + ${maven-compiler-plugin.version} -Werror @@ -270,16 +306,15 @@ -Xlint:-options -Xlint:-processing -Xlint:-serial + -Xlint:-classfile true - ${java.version} - ${java.version} org.apache.maven.plugins maven-jar-plugin - 3.3.0 + ${maven-jar-plugin.version} @@ -296,12 +331,12 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + ${maven-deploy-plugin.version} org.apache.maven.plugins maven-enforcer-plugin - 3.4.1 + ${maven-enforcer-plugin.version} enforce-no-snapshots @@ -322,7 +357,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + ${maven-javadoc-plugin.version} io.r2dbc.postgresql.authentication,io.r2dbc.postgresql.client,io.r2dbc.postgresql.message,io.r2dbc.postgresql.util @@ -345,7 +380,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + ${maven-source-plugin.version} attach-javadocs @@ -358,7 +393,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.3 + ${maven-surefire-plugin.version} random @@ -367,6 +402,9 @@ **/*Tests.java + + -Dfile.encoding=${project.build.sourceEncoding} + paranoid @@ -375,7 +413,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.2.3 + ${maven-failsafe-plugin.version} @@ -390,6 +428,9 @@ **/*TestKit.java **/*IntegrationTests.java + + -Dfile.encoding=${project.build.sourceEncoding} + paranoid @@ -398,7 +439,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.5.0 + ${flatten-maven-plugin.version} flatten @@ -472,7 +513,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.5.0 + ${build-helper-maven-plugin.version} add-source @@ -506,7 +547,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.1 + ${exec-maven-plugin.version} run-benchmarks @@ -558,7 +599,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + ${maven-gpg-plugin.version} sign-artifacts @@ -581,7 +622,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + ${nexus-staging-maven-plugin.version} true sonatype diff --git a/src/main/java/io/r2dbc/postgresql/authentication/SASLAuthenticationHandler.java b/src/main/java/io/r2dbc/postgresql/authentication/SASLAuthenticationHandler.java index 0ca21ac9b..653f03821 100644 --- a/src/main/java/io/r2dbc/postgresql/authentication/SASLAuthenticationHandler.java +++ b/src/main/java/io/r2dbc/postgresql/authentication/SASLAuthenticationHandler.java @@ -1,7 +1,6 @@ package io.r2dbc.postgresql.authentication; import com.ongres.scram.client.ScramClient; -import com.ongres.scram.common.StringPreparation; import com.ongres.scram.common.exception.ScramException; import com.ongres.scram.common.util.TlsServerEndpoint; import io.r2dbc.postgresql.client.ConnectionContext; @@ -25,6 +24,9 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import static com.ongres.scram.common.StringPreparation.POSTGRESQL_PREPARATION; +import static com.ongres.scram.common.util.TlsServerEndpoint.TLS_SERVER_END_POINT; + public class SASLAuthenticationHandler implements AuthenticationHandler { private static final Logger LOG = Loggers.getLogger(SASLAuthenticationHandler.class); @@ -82,22 +84,16 @@ public FrontendMessage handle(AuthenticationMessage message) { } private FrontendMessage handleAuthenticationSASL(AuthenticationSASL message) { - - char[] password = new char[this.password.length()]; - for (int i = 0; i < password.length; i++) { - password[i] = this.password.charAt(i); - } - ScramClient.FinalBuildStage builder = ScramClient.builder() .advertisedMechanisms(message.getAuthenticationMechanisms()) .username(this.username) // ignored by the server, use startup message - .password(password) - .stringPreparation(StringPreparation.POSTGRESQL_PREPARATION); + .password(password.toString().toCharArray()) + .stringPreparation(POSTGRESQL_PREPARATION); SSLSession sslSession = this.context.getSslSession(); if (sslSession != null && sslSession.isValid()) { - builder.channelBinding(TlsServerEndpoint.TLS_SERVER_END_POINT, extractSslEndpoint(sslSession)); + builder.channelBinding(TLS_SERVER_END_POINT, extractSslEndpoint(sslSession)); } this.scramClient = builder.build(); @@ -107,14 +103,9 @@ private FrontendMessage handleAuthenticationSASL(AuthenticationSASL message) { private static byte[] extractSslEndpoint(SSLSession sslSession) { try { - Certificate[] certificates = sslSession.getPeerCertificates(); - if (certificates != null && certificates.length > 0) { - Certificate peerCert = certificates[0]; // First certificate is the peer's certificate - if (peerCert instanceof X509Certificate) { - X509Certificate cert = (X509Certificate) peerCert; - return TlsServerEndpoint.getChannelBindingData(cert); - - } + Certificate[] certificates = sslSession.getPeerCertificates(); // First certificate is the peer's certificate + if (certificates != null && certificates.length > 0 && certificates[0] instanceof X509Certificate ) { + return TlsServerEndpoint.getChannelBindingData((X509Certificate) certificates[0]); } } catch (CertificateException | SSLException e) { LOG.debug("Cannot extract X509Certificate from SSL session", e); @@ -125,7 +116,6 @@ private static byte[] extractSslEndpoint(SSLSession sslSession) { private FrontendMessage handleAuthenticationSASLContinue(AuthenticationSASLContinue message) { try { this.scramClient.serverFirstMessage(ByteBufferUtils.decode(message.getData())); - return new SASLResponse(ByteBufferUtils.encode(this.scramClient.clientFinalMessage().toString())); } catch (ScramException e) { throw Exceptions.propagate(e); diff --git a/src/test/java/io/r2dbc/postgresql/PgBouncerIntegrationTests.java b/src/test/java/io/r2dbc/postgresql/PgBouncerIntegrationTests.java index 203d96796..fab77b2a9 100644 --- a/src/test/java/io/r2dbc/postgresql/PgBouncerIntegrationTests.java +++ b/src/test/java/io/r2dbc/postgresql/PgBouncerIntegrationTests.java @@ -30,7 +30,7 @@ final class PgBouncerIntegrationTests { @RegisterExtension - static final PostgresqlServerExtension SERVER = new PostgresqlServerExtension(); + static final PostgresqlServerExtension SERVER = new PostgresqlServerExtension("pg_hba_pgbouncer.conf"); @ParameterizedTest @ValueSource(strings = {"transaction", "statement"}) diff --git a/src/test/java/io/r2dbc/postgresql/PostgresqlConnectionFactoryUnitTests.java b/src/test/java/io/r2dbc/postgresql/PostgresqlConnectionFactoryUnitTests.java index cb6db4f23..a52384e1b 100644 --- a/src/test/java/io/r2dbc/postgresql/PostgresqlConnectionFactoryUnitTests.java +++ b/src/test/java/io/r2dbc/postgresql/PostgresqlConnectionFactoryUnitTests.java @@ -36,6 +36,7 @@ import java.util.Collections; +import static com.ongres.scram.common.StringPreparation.POSTGRESQL_PREPARATION; import static io.r2dbc.postgresql.util.TestByteBufAllocator.TEST; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -85,6 +86,7 @@ void createAuthenticationSASL() { .advertisedMechanisms(Collections.singletonList("SCRAM-SHA-256")) .username("test-username") .password("test-password".toCharArray()) + .stringPreparation(POSTGRESQL_PREPARATION) .build(); // @formatter:off @@ -103,6 +105,12 @@ void createAuthenticationSASL() { .username("test-username") .password("test-password") .build(); + + new PostgresqlConnectionFactory(testClientFactory(client, configuration), configuration) + .create() + .as(StepVerifier::create) + .expectNextCount(1) + .verifyComplete(); } @Test diff --git a/src/test/java/io/r2dbc/postgresql/client/ReactorNettyClientIntegrationTests.java b/src/test/java/io/r2dbc/postgresql/client/ReactorNettyClientIntegrationTests.java index c03aba09a..c90b2a466 100644 --- a/src/test/java/io/r2dbc/postgresql/client/ReactorNettyClientIntegrationTests.java +++ b/src/test/java/io/r2dbc/postgresql/client/ReactorNettyClientIntegrationTests.java @@ -22,7 +22,7 @@ import io.r2dbc.postgresql.PostgresqlConnectionConfiguration; import io.r2dbc.postgresql.PostgresqlConnectionFactory; import io.r2dbc.postgresql.api.PostgresqlConnection; -import io.r2dbc.postgresql.authentication.PasswordAuthenticationHandler; +import io.r2dbc.postgresql.authentication.SASLAuthenticationHandler; import io.r2dbc.postgresql.message.backend.BackendMessage; import io.r2dbc.postgresql.message.backend.CommandComplete; import io.r2dbc.postgresql.message.backend.DataRow; @@ -86,20 +86,26 @@ final class ReactorNettyClientIntegrationTests { private final ReactorNettyClient client = ReactorNettyClient.connect(SERVER.getHost(), SERVER.getPort()) .delayUntil(client -> StartupMessageFlow - .exchange(this.getClass().getName(), m -> new PasswordAuthenticationHandler(SERVER.getPassword(), SERVER.getUsername()), client, SERVER.getDatabase(), SERVER.getUsername())) + .exchange(this.getClass().getName(), m -> new SASLAuthenticationHandler(SERVER.getPassword(), SERVER.getUsername(), client.getContext()), client, SERVER.getDatabase(), SERVER.getUsername())) .block(); @BeforeEach void before() { - SERVER.getJdbcOperations().execute("DROP TABLE IF EXISTS test"); - SERVER.getJdbcOperations().execute("CREATE TABLE test ( value INTEGER )"); + if (SERVER.getJdbcOperations() != null) { + SERVER.getJdbcOperations().execute("DROP TABLE IF EXISTS test"); + SERVER.getJdbcOperations().execute("CREATE TABLE test ( value INTEGER )"); + } } @AfterEach void after() { - SERVER.getJdbcOperations().execute("DROP TABLE IF EXISTS test"); - this.client.close() - .block(); + if (SERVER.getJdbcOperations() != null) { + SERVER.getJdbcOperations().execute("DROP TABLE IF EXISTS test"); + } + if (this.client != null) { + this.client.close() + .block(); + } } @Test @@ -312,11 +318,10 @@ void timeoutTest() { @Test @DisabledOnOs(OS.WINDOWS) void unixDomainSocketTest() { - String socket = "/tmp/.s.PGSQL.5432"; assumeThat(KQueue.isAvailable() || Epoll.isAvailable()).describedAs("EPoll or KQueue must be available").isTrue(); - assumeThat(new File(socket)).exists(); + assumeThat(new File(socket)).describedAs("Local server must be running").exists(); PostgresqlConnectionFactory postgresqlConnectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder() .socket(socket) diff --git a/src/test/java/io/r2dbc/postgresql/codec/HStoreCodecUnitTests.java b/src/test/java/io/r2dbc/postgresql/codec/HStoreCodecUnitTests.java index 96fc406e2..1af36766c 100644 --- a/src/test/java/io/r2dbc/postgresql/codec/HStoreCodecUnitTests.java +++ b/src/test/java/io/r2dbc/postgresql/codec/HStoreCodecUnitTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -52,6 +53,8 @@ void constructorNoByteBufAllocator() { @Test void decodeAsText() { ByteBuf buffer = TEST.buffer(); + // The test expects the JVM running with JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 + assertThat(Charset.defaultCharset()).isEqualTo(StandardCharsets.UTF_8); buffer.writeCharSequence("\"b\"=>\"\\\"2.2\", \"a\\\"\"=>\"1\", \"c\"=>NULL, \"d\"=>\"Zoë\", \"é\"=>\"120°\"", Charset.defaultCharset()); Map res = new HStoreCodec(TEST, dataType).decode(buffer, dataType, Format.FORMAT_TEXT, Map.class); Map expect = new HashMap<>(); diff --git a/src/test/java/io/r2dbc/postgresql/util/PgBouncer.java b/src/test/java/io/r2dbc/postgresql/util/PgBouncer.java index 37593649c..9adcf291e 100644 --- a/src/test/java/io/r2dbc/postgresql/util/PgBouncer.java +++ b/src/test/java/io/r2dbc/postgresql/util/PgBouncer.java @@ -25,13 +25,14 @@ */ public final class PgBouncer implements AutoCloseable { - public static String IMAGE_NAME = "edoburu/pgbouncer:1.9.0"; + public static String IMAGE_NAME = "edoburu/pgbouncer:1.22.0-p0"; private final GenericContainer container; public PgBouncer(PostgresqlServerExtension server, String poolMode) { this.container = new GenericContainer<>(IMAGE_NAME) .withExposedPorts(PostgreSQLContainer.POSTGRESQL_PORT) + .withEnv("AUTH_TYPE", "scram-sha-256") .withEnv("POOL_MODE", poolMode) .withEnv("SERVER_RESET_QUERY_ALWAYS", "1") .withEnv("DB_USER", server.getUsername()) diff --git a/src/test/java/io/r2dbc/postgresql/util/PgPool.java b/src/test/java/io/r2dbc/postgresql/util/PgPool.java index b0105403a..2485c522a 100644 --- a/src/test/java/io/r2dbc/postgresql/util/PgPool.java +++ b/src/test/java/io/r2dbc/postgresql/util/PgPool.java @@ -28,7 +28,7 @@ public final class PgPool implements AutoCloseable { private final GenericContainer container; public PgPool(PostgresqlServerExtension server) { - this.container = new GenericContainer<>("bitnami/pgpool:4.1.0") + this.container = new GenericContainer<>("bitnami/pgpool:4.5.2") .withExposedPorts(PostgreSQLContainer.POSTGRESQL_PORT) .withEnv("PGPOOL_BACKEND_NODES", String.format("0:%s:%s", server.getPostgres().getNetworkAlias(), PostgreSQLContainer.POSTGRESQL_PORT)) .withEnv("PGPOOL_SR_CHECK_USER", server.getUsername()) diff --git a/src/test/java/io/r2dbc/postgresql/util/PostgresqlHighAvailabilityClusterExtension.java b/src/test/java/io/r2dbc/postgresql/util/PostgresqlHighAvailabilityClusterExtension.java index 38cb33ddd..088310196 100644 --- a/src/test/java/io/r2dbc/postgresql/util/PostgresqlHighAvailabilityClusterExtension.java +++ b/src/test/java/io/r2dbc/postgresql/util/PostgresqlHighAvailabilityClusterExtension.java @@ -21,11 +21,9 @@ import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; -import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.testcontainers.containers.Network; import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; diff --git a/src/test/java/io/r2dbc/postgresql/util/PostgresqlServerExtension.java b/src/test/java/io/r2dbc/postgresql/util/PostgresqlServerExtension.java index 67ce96f54..d4fe4935d 100644 --- a/src/test/java/io/r2dbc/postgresql/util/PostgresqlServerExtension.java +++ b/src/test/java/io/r2dbc/postgresql/util/PostgresqlServerExtension.java @@ -48,7 +48,7 @@ */ public final class PostgresqlServerExtension implements BeforeAllCallback, AfterAllCallback { - static final String IMAGE_NAME = "postgres:13.3"; + static final String IMAGE_NAME = "postgres:16-alpine"; static PostgreSQLContainer containerInstance = null; @@ -64,15 +64,24 @@ public final class PostgresqlServerExtension implements BeforeAllCallback, After return PostgresqlServerExtension.containerInstance = container(); }; - private final DatabaseContainer postgres = getContainer(); + private final DatabaseContainer postgres; - private final boolean useTestContainer = this.postgres instanceof TestContainer; + private final boolean useTestContainer; private HikariDataSource dataSource; private JdbcOperations jdbcOperations; + private final String hbaConf; + public PostgresqlServerExtension() { + this("pg_hba.conf"); + } + + public PostgresqlServerExtension(String hbaConf) { + this.hbaConf = hbaConf; + this.postgres = getContainer(); + this.useTestContainer = postgres instanceof TestContainer; } private DatabaseContainer getContainer() { @@ -191,7 +200,7 @@ private > T container() { .withCopyFileToContainer(getHostPath("server.crt", 0600), "/var/server.crt") .withCopyFileToContainer(getHostPath("server.key", 0600), "/var/server.key") .withCopyFileToContainer(getHostPath("client.crt", 0600), "/var/client.crt") - .withCopyFileToContainer(getHostPath("pg_hba.conf", 0600), "/var/pg_hba.conf") + .withCopyFileToContainer(getHostPath(hbaConf, 0600), "/var/pg_hba.conf") .withCopyFileToContainer(getHostPath("setup.sh", 0755), "/var/setup.sh") .withCopyFileToContainer(getHostPath("test-db-init-script.sql", 0755), "/docker-entrypoint-initdb.d/test-db-init-script.sql") .withReuse(true) diff --git a/src/test/resources/pg_hba.conf b/src/test/resources/pg_hba.conf index 6330483ea..6f7d48e99 100644 --- a/src/test/resources/pg_hba.conf +++ b/src/test/resources/pg_hba.conf @@ -4,3 +4,5 @@ hostssl all test-ssl all password hostssl all test-ssl-scram all scram-sha-256 hostssl all test-ssl-with-cert all cert local all all md5 + +# host all all all scram-sha-256 diff --git a/src/test/resources/pg_hba_pgbouncer.conf b/src/test/resources/pg_hba_pgbouncer.conf new file mode 100644 index 000000000..33ce39341 --- /dev/null +++ b/src/test/resources/pg_hba_pgbouncer.conf @@ -0,0 +1,8 @@ +hostnossl all test all md5 +hostnossl all test-scram all scram-sha-256 +hostssl all test-ssl all password +hostssl all test-ssl-with-cert all cert +local all all md5 + +# for PgBouncerIntegrationTests +host all all all scram-sha-256 diff --git a/src/test/resources/setup-standby.sh b/src/test/resources/setup-standby.sh index 13a5f7bfc..a8e4f78a6 100644 --- a/src/test/resources/setup-standby.sh +++ b/src/test/resources/setup-standby.sh @@ -19,4 +19,9 @@ EOF fi sed -i 's/wal_level = hot_standby/wal_level = replica/g' "${PGDATA}"/postgresql.conf echo "ready to run" -exec gosu postgres postgres +# gosu isn't installed in alpine: https://github.com/docker-library/postgres/blob/master/Dockerfile-alpine.template +if [ -x "$(type gosu >/dev/null 2>&1)" ]; then + exec gosu postgres postgres +else + exec su-exec postgres postgres +fi diff --git a/test.bash b/test.bash index 2880206a5..005e39917 100755 --- a/test.bash +++ b/test.bash @@ -1,16 +1,20 @@ #!/usr/bin/env bash -docker run -it \ +# https://github.com/docker-library/postgres/blob/master/Dockerfile-alpine.template +chmod 0600 "$(pwd)/src/test/resources/server.key" + +docker run --rm -it \ + --user 70:70 \ -e "POSTGRES_USER=test" \ -e "POSTGRES_PASSWORD=test" \ -e "POSTGRES_DB=test" \ - --mount type=bind,source="$(pwd)/src/test/resources/server.crt",target=/var/server.crt \ + --mount type=bind,source="$(pwd)/src/test/resources/server.crt",target=/var/server.crt,readonly \ --mount type=bind,source="$(pwd)/src/test/resources/server.key",target=/var/server.key \ - --mount type=bind,source="$(pwd)/src/test/resources/client.crt",target=/var/client.crt \ - --mount type=bind,source="$(pwd)/src/test/resources/pg_hba.conf",target=/var/pg_hba.conf \ - --mount type=bind,source="$(pwd)/src/test/resources/setup.sh",target=/var/setup.sh \ - --mount type=bind,source="$(pwd)/src/test/resources/test-db-init-script.sql",target=/docker-entrypoint-initdb.d/test-db-init-script.sql \ - postgres:11.1 \ + --mount type=bind,source="$(pwd)/src/test/resources/client.crt",target=/var/client.crt,readonly \ + --mount type=bind,source="$(pwd)/src/test/resources/pg_hba.conf",target=/var/pg_hba.conf,readonly \ + --mount type=bind,source="$(pwd)/src/test/resources/setup.sh",target=/var/setup.sh,readonly \ + --mount type=bind,source="$(pwd)/src/test/resources/test-db-init-script.sql",target=/docker-entrypoint-initdb.d/test-db-init-script.sql,readonly \ + postgres:16-alpine \ -c 'ssl=on' \ -c 'ssl_key_file=/var/server.key' \ -c 'ssl_cert_file=/var/server.crt' \