diff --git a/.github/workflows/mvn-release-prepare-perform.yaml b/.github/workflows/mvn-release-prepare-perform.yaml
index c858555..3a93fc1 100644
--- a/.github/workflows/mvn-release-prepare-perform.yaml
+++ b/.github/workflows/mvn-release-prepare-perform.yaml
@@ -24,24 +24,24 @@ jobs:
steps:
- id: 'checkout'
name: 'Step: Check Out Project'
- uses: 'actions/checkout@v4'
+ uses: 'actions/checkout@v6'
with:
fetch-depth: 1
persist-credentials: false
- id: 'setup-java'
name: 'Step: Set Up Java and Maven'
- uses: 'actions/setup-java@v4'
+ uses: 'actions/setup-java@v5'
with:
cache: 'maven'
distribution: 'temurin'
gpg-passphrase: 'GPG_PASSPHRASE'
gpg-private-key: '${{ secrets.GPG_PRIVATE_KEY }}'
- java-version: '23'
- mvn-toolchain-id: 'Temurin 23'
+ java-version: '25'
+ mvn-toolchain-id: 'Temurin 25'
mvn-toolchain-vendor: 'openjdk' # see ../../pom.xml
- server-id: 'sonatype-oss-repository-hosting' # see https://github.com/microbean/microbean-parent/blob/master/pom.xml#L38
- server-password: 'SONATYPE_OSSRH_PASSWORD'
- server-username: 'SONATYPE_OSSRH_USERNAME'
+ server-id: 'central.sonatype.com'
+ server-password: 'CENTRAL_SONATYPE_COM_PASSWORD'
+ server-username: 'CENTRAL_SONATYPE_COM_USERNAME'
- id: 'setup-askpass'
name: 'Step: Set Up GIT_ASKPASS'
run: |
@@ -58,6 +58,8 @@ jobs:
- id: 'mvn-release-prepare'
name: 'Step: Maven Release: Prepare, Perform and Publish Site'
env:
+ CENTRAL_SONATYPE_COM_PASSWORD: '${{ secrets.CENTRAL_SONATYPE_COM_PASSWORD }}'
+ CENTRAL_SONATYPE_COM_USERNAME: '${{ secrets.CENTRAL_SONATYPE_COM_USERNAME }}'
DRY_RUN: '${{ inputs.dryRun }}'
GIT_ASKPASS: '${{ runner.temp }}/.askpass'
GPG_PASSPHRASE: '${{ secrets.GPG_PASSPHRASE }}'
@@ -65,9 +67,6 @@ jobs:
MVN_TRANSFER_LOGGING: ${{ inputs.mvnTransferLogging && '' || '--no-transfer-progress' }}
PUSH_TOKEN : '${{ secrets.PUSH_TOKEN }}' # critical; see ${GIT_ASKPASS} file
SCM_GIT_HTTPS_URL: 'scm:git:${{ github.server_url }}/${{ github.repository }}.git'
- SONATYPE_OSSRH_PASSWORD: '${{ secrets.SONATYPE_OSSRH_PASSWORD }}'
- SONATYPE_OSSRH_STAGING_PROFILE_ID: '${{ vars.SONATYPE_OSSRH_STAGING_PROFILE_ID }}'
- SONATYPE_OSSRH_USERNAME: '${{ secrets.SONATYPE_OSSRH_USERNAME }}'
shell: 'bash -e {0}'
run: >
git config --global user.email 'ci@microbean.org'
@@ -75,12 +74,12 @@ jobs:
git config --global user.name 'microbean'
echo "::group::Running mvn prepare"
-
+
./mvnw --batch-mode ${MVN_DEBUG} --errors ${MVN_TRANSFER_LOGGING} release:prepare
-DdryRun="${DRY_RUN}"
-Darguments="${MVN_TRANSFER_LOGGING}"
-Dscm.url="${SCM_GIT_HTTPS_URL}"
-
+
scm_tag="$(grep '^scm.tag=' release.properties | cut -f 2 -d =)"
echo "Prepared ${scm_tag}" >> "${GITHUB_STEP_SUMMARY}"
@@ -90,37 +89,13 @@ jobs:
echo "::endgroup::"
echo "::group::Running mvn perform"
-
- set +e
- {
./mvnw --batch-mode ${MVN_DEBUG} --errors ${MVN_TRANSFER_LOGGING} release:perform
- -Darguments="${MVN_TRANSFER_LOGGING} -Dscmpublish.dryRun=${DRY_RUN} -Dscmpublish.pubScmUrl=${SCM_GIT_HTTPS_URL} -DskipTests -DstagingProfileId=${SONATYPE_OSSRH_STAGING_PROFILE_ID}"
+ -Darguments="${MVN_TRANSFER_LOGGING} -Dscmpublish.dryRun=${DRY_RUN} -Dscmpublish.pubScmUrl=${SCM_GIT_HTTPS_URL} -DskipTests -DautoPublish=true -DwaitUntil=published -DwaitMaxTime=3600"
-DdryRun="${DRY_RUN}"
-Dgoals="process-classes,post-site,scm-publish:publish-scm,deploy"
-Dscm.url="${SCM_GIT_HTTPS_URL}"
- |
- tee /dev/fd/3
- |
- grep --invert-match --silent 'Java class com.sonatype.nexus.staging.api.dto.StagingProfileRepositoryDTO' || cat > /dev/null
- ;
- }
- 3>&1
- exit_codes=(${PIPESTATUS[@]})
+ echo "Released ${scm_tag} successfully" >> "${GITHUB_STEP_SUMMARY}";
echo "::endgroup::"
-
- set -e
-
- if [ "${exit_codes[2]}" -ne 0 ] ; then
- # grep "failed" (found com.sonatype.nexus.staging.api.dto.StagingProfileRepositoryDTO) and mvn failed
- echo "Released ${scm_tag} successfully, but verify that the staging repository was successfully released" >> "${GITHUB_STEP_SUMMARY}";
- # Treat this as a successful run
- exit 0;
- elif [ "${exit_codes[0]}" -eq 0 ] ; then
- # mvn succeeded and grep "succeeded" (did not find com.sonatype.nexus.staging.api.dto.StagingProfileRepositoryDTO)
- echo "Released ${scm_tag} successfully" >> "${GITHUB_STEP_SUMMARY}";
- fi
-
- exit "${exit_codes[0]}"
diff --git a/.github/workflows/mvn-verify.yaml b/.github/workflows/mvn-verify.yaml
index a414901..faefc80 100644
--- a/.github/workflows/mvn-verify.yaml
+++ b/.github/workflows/mvn-verify.yaml
@@ -12,18 +12,18 @@ jobs:
steps:
- id: 'checkout'
name: 'Step: Checkout'
- uses: 'actions/checkout@v4'
+ uses: 'actions/checkout@v6'
with:
fetch-depth: 1
persist-credentials: false
- id: 'setup-java'
name: 'Step: Set Up Java and Maven'
- uses: 'actions/setup-java@v4'
+ uses: 'actions/setup-java@v5'
with:
cache: 'maven'
distribution: 'temurin'
- java-version: '23'
- mvn-toolchain-id: 'Temurin 23'
+ java-version: '25'
+ mvn-toolchain-id: 'Temurin 25'
mvn-toolchain-vendor: 'openjdk' # see ../../pom.xml
- id: 'mvn-verify'
name: 'Step: Maven Verify'
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index bca10a6..c652895 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1,20 +1,13 @@
-# 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
+# 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
+# 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.4
distributionType=only-script
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
-
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
diff --git a/README.md b/README.md
index 3c55857..d8e8472 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ Client Proxy: Byte Buddy as a Maven dependency:
org.microbean
microbean-clientproxy-bytebuddy
- 0.0.1
+ 0.0.2
```
diff --git a/mvnw b/mvnw
index 19529dd..bd8896b 100755
--- a/mvnw
+++ b/mvnw
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
-# Apache Maven Wrapper startup batch script, version 3.3.2
+# Apache Maven Wrapper startup batch script, version 3.3.4
#
# Optional ENV vars
# -----------------
@@ -105,14 +105,17 @@ trim() {
printf "%s" "${1}" | tr -d '[:space:]'
}
+scriptDir="$(dirname "$0")"
+scriptName="$(basename "$0")"
+
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
-done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
@@ -130,7 +133,7 @@ maven-mvnd-*bin.*)
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
-*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
@@ -227,7 +230,7 @@ if [ -n "${distributionSha256Sum-}" ]; then
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
- if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
@@ -252,8 +255,41 @@ if command -v unzip >/dev/null; then
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
-printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
-mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+actualDistributionDir=""
+
+# First try the expected directory name (for regular distributions)
+if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
+ if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$distributionUrlNameMain"
+ fi
+fi
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if [ -z "$actualDistributionDir" ]; then
+ # enable globbing to iterate over items
+ set +f
+ for dir in "$TMP_DOWNLOAD_DIR"/*; do
+ if [ -d "$dir" ]; then
+ if [ -f "$dir/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$(basename "$dir")"
+ break
+ fi
+ fi
+ done
+ set -f
+fi
+
+if [ -z "$actualDistributionDir" ]; then
+ verbose "Contents of $TMP_DOWNLOAD_DIR:"
+ verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
+ die "Could not find Maven distribution directory in extracted archive"
+fi
+
+verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
index b150b91..5761d94 100644
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -19,7 +19,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
-@REM Apache Maven Wrapper startup batch script, version 3.3.2
+@REM Apache Maven Wrapper startup batch script, version 3.3.4
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@@ -40,7 +40,7 @@
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
-@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
+@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
@@ -73,16 +73,30 @@ switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
if ($env:MVNW_REPOURL) {
- $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
- $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
+ $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
-$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
+
+$MAVEN_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
- $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
+ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
+}
+
+if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
+ New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
+}
+
+$MAVEN_WRAPPER_DISTS = $null
+if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
+ $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
+} else {
+ $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
-$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+
+$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
@@ -134,7 +148,33 @@ if ($distributionSha256Sum) {
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
-Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+$actualDistributionDir = ""
+
+# First try the expected directory name (for regular distributions)
+$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
+$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
+if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
+ $actualDistributionDir = $distributionUrlNameMain
+}
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if (!$actualDistributionDir) {
+ Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
+ $testPath = Join-Path $_.FullName "bin/$MVN_CMD"
+ if (Test-Path -Path $testPath -PathType Leaf) {
+ $actualDistributionDir = $_.Name
+ }
+ }
+}
+
+if (!$actualDistributionDir) {
+ Write-Error "Could not find Maven distribution directory in extracted archive"
+}
+
+Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
diff --git a/pom.xml b/pom.xml
index 7c5979f..7e62158 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,7 +89,6 @@
deployment
[maven-release-plugin] [skip ci]
v@{project.version}
- false
@@ -101,12 +100,8 @@
true
false
-
-
- true
-
- https://oss.sonatype.org/
- 10
+
+ ${project.name} v${project.version}
UTF8
@@ -125,7 +120,7 @@
org.junit
junit-bom
- 5.12.1
+ 6.0.1
pom
import
@@ -135,33 +130,51 @@
net.bytebuddy
byte-buddy
- 1.17.3
+ 1.18.3
+
+
+
+ org.microbean
+ microbean-assign
+ 0.0.11
org.microbean
microbean-bean
- 0.0.16
+ 0.0.22
org.microbean
microbean-construct
- 0.0.10
+ 0.0.18
+
+
+
+ org.microbean
+ microbean-producer
+ 0.0.3
+
+
+
+ org.microbean
+ microbean-proxy
+ 0.0.5
org.microbean
microbean-reference
- 0.0.2
+ 0.0.5
org.microbean
microbean-scopelet
- 0.0.7
+ 0.0.11
-
+
@@ -173,6 +186,12 @@
compile
+
+ org.microbean
+ microbean-assign
+ compile
+
+
org.microbean
microbean-bean
@@ -185,6 +204,12 @@
compile
+
+ org.microbean
+ microbean-proxy
+ compile
+
+
org.microbean
microbean-reference
@@ -205,12 +230,18 @@
test
+
+ org.microbean
+ microbean-producer
+ test
+
+
org.microbean
microbean-scopelet
test
-
+
@@ -218,11 +249,11 @@
maven-antrun-plugin
- 3.1.0
+ 3.2.0
maven-assembly-plugin
- 3.7.1
+ 3.8.0
maven-checkstyle-plugin
@@ -332,13 +363,13 @@
com.puppycrawl.tools
checkstyle
- 10.12.6
+ 12.3.0
maven-clean-plugin
- 3.4.0
+ 3.5.0
@@ -353,49 +384,42 @@
maven-compiler-plugin
- 3.13.0
+ 3.14.1
-Xlint:all
-parameters
-
-
- org.codehaus.plexus
- plexus-java
- 1.3.0
-
-
maven-dependency-plugin
- 3.8.1
+ 3.9.0
maven-deploy-plugin
- 3.1.3
+ 3.1.4
maven-enforcer-plugin
- 3.5.0
+ 3.6.2
maven-gpg-plugin
- 3.2.7
+ 3.2.8
maven-install-plugin
- 3.1.3
+ 3.1.4
maven-jar-plugin
- 3.4.2
+ 3.5.0
maven-javadoc-plugin
- 3.11.2
+ 3.12.0
true
@@ -423,20 +447,19 @@
maven-project-info-reports-plugin
- 3.8.0
+ 3.9.0
maven-release-plugin
-
- 3.1.1
+ 3.3.1
maven-resources-plugin
- 3.3.1
+ 3.4.0
maven-scm-plugin
- 2.1.0
+ 2.2.1
maven-scm-publish-plugin
@@ -448,7 +471,7 @@
maven-source-plugin
- 3.3.1
+ 3.4.0
attach-sources
@@ -460,7 +483,7 @@
maven-surefire-plugin
- 3.5.2
+ 3.5.4
-XX:StartFlightRecording=duration=10s,filename=${project.build.directory}/recording.jfr
@@ -472,35 +495,25 @@
com.github.spotbugs
spotbugs-maven-plugin
- 4.8.6.6
+ 4.9.8.2
org.codehaus.mojo
versions-maven-plugin
- 2.18.0
+ 2.20.1
io.smallrye
jandex-maven-plugin
- 3.2.3
+ 3.5.3
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.13
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.9.0
true
-
-
-
- com.thoughtworks.xstream
- xstream
- 1.4.20
-
-
- sonatype-oss-repository-hosting
- ${nexusUrl}
- ${autoReleaseAfterClose}
+ central.sonatype.com
@@ -521,7 +534,7 @@
23
- 3.9.9
+ 3.9.12
@@ -546,8 +559,8 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
+ org.sonatype.central
+ central-publishing-maven-plugin
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 6959a7b..de403a9 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -13,7 +13,7 @@
*/
/**
- * Provides packages related to implementing {@linkplain org.microbean.reference.ClientProxy client proxies}
+ * Provides packages related to implementing {@linkplain org.microbean.proxy.Proxy client proxies}
* using Byte Buddy.
*
* @author Laird Nelson
@@ -23,9 +23,10 @@
exports org.microbean.clientproxy.bytebuddy;
requires transitive net.bytebuddy;
-
+ requires org.microbean.assign;
requires transitive org.microbean.bean;
- requires transitive org.microbean.construct;
+ requires org.microbean.construct;
+ requires transitive org.microbean.proxy;
requires transitive org.microbean.reference;
}
diff --git a/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxier.java b/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxier.java
index b5e97b7..157c668 100644
--- a/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxier.java
+++ b/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxier.java
@@ -16,35 +16,49 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
+import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+import java.util.function.Supplier;
+
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.pool.TypePool;
+import org.microbean.bean.Id;
+
import org.microbean.construct.Domain;
-import org.microbean.reference.AbstractClientProxier;
-import org.microbean.reference.ProxySpecification;
+import org.microbean.proxy.AbstractToolkitProxier;
+import org.microbean.proxy.Proxy;
+import org.microbean.proxy.ProxySpecification;
+
+import org.microbean.reference.ClientProxier;
+import org.microbean.reference.ReferenceException;
+
+import static java.lang.invoke.MethodType.methodType;
/**
- * An {@link AbstractClientProxier} that uses Byte Buddy to {@linkplain
- * #generate(ProxySpecification) generate} {@linkplain org.microbean.reference.ClientProxy client proxies}.
+ * An {@link AbstractToolkitProxier} and {@link ClientProxier} that uses Byte
+ * Buddy to {@linkplain #generate(ProxySpecification) generate} {@linkplain org.microbean.proxy.Proxy client
+ * proxies}.
*
* @author Laird Nelson
*
* @see BBClientProxyClassGenerator
*/
-public final class BBClientProxier extends AbstractClientProxier> {
+public final class BBClientProxier extends AbstractToolkitProxier> implements ClientProxier {
+ private static final Map clientProxyInstances = new ConcurrentHashMap<>();
+
private final TypeDefinitions tds;
private final BBClientProxyClassGenerator g;
- private static final Lookup lookup = MethodHandles.lookup(); // or instance variable?
-
/**
* Creates a new {@link BBClientProxier}.
*
@@ -94,11 +108,16 @@ public BBClientProxier(final Domain domain,
public BBClientProxier(final Domain domain,
final TypeDefinitions tds,
final BBClientProxyClassGenerator g) {
- super(domain);
+ super(domain, MethodHandles.lookup());
this.tds = Objects.requireNonNull(tds, "tds");
this.g = Objects.requireNonNull(g, "g");
}
+ @Override // ClientProxier
+ public R clientProxy(final Id id, final Supplier extends R> instanceSupplier) {
+ return this.proxy(new ProxySpecification(this.domain(), id), instanceSupplier).$cast();
+ }
+
@Override // AbstractClientProxier>
protected final DynamicType.Unloaded> generate(final ProxySpecification ps) {
return
@@ -107,8 +126,28 @@ protected final DynamicType.Unloaded> generate(final ProxySpecification ps) {
ps.interfaces().stream().map(this.tds::typeDescriptionGeneric).toList());
}
+ @Override // AbstractToolkitProxier>
+ @SuppressWarnings("unchecked")
+ public final Proxy proxy(final ProxySpecification ps, final Supplier extends R> instanceSupplier) {
+ return (Proxy)clientProxyInstances.computeIfAbsent(ps, ps0 -> {
+ try {
+ final Class> proxyClass = this.proxyClass(ps);
+ this.getClass().getModule().addReads(proxyClass.getModule());
+ return
+ this.lookup(proxyClass).findConstructor(proxyClass, methodType(void.class, Supplier.class))
+ .asType(methodType(Object.class, Supplier.class))
+ .invokeExact(instanceSupplier);
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new ReferenceException(e.getMessage(), e);
+ }
+ });
+ }
+
+
@Override // AbstractClientProxier>
- protected final Class> clientProxyClass(final DynamicType.Unloaded> dtu, final ClassLoader cl)
+ protected final Class> proxyClass(final DynamicType.Unloaded> dtu, final ClassLoader cl)
throws ClassNotFoundException {
// getTypeName() invoked on a TypeDescription will be its binary name (required by Class#forName(String)):
// https://javadoc.io/static/net.bytebuddy/byte-buddy/1.17.3/net/bytebuddy/description/type/TypeDefinition.html#getTypeName--
@@ -117,9 +156,4 @@ protected final Class> clientProxyClass(final DynamicType.Unloaded> dtu, fin
return dtu.load(superclass.getClassLoader(), ClassLoadingStrategy.UsingLookup.of(lookup(superclass))).getLoaded();
}
- @Override // AbstractClientProxier>
- protected final Lookup lookup(final Class> c) {
- return lookup.in(c);
- }
-
}
diff --git a/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxyClassGenerator.java b/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxyClassGenerator.java
index 6da1046..0959e55 100644
--- a/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxyClassGenerator.java
+++ b/src/main/java/org/microbean/clientproxy/bytebuddy/BBClientProxyClassGenerator.java
@@ -15,7 +15,6 @@
import java.util.Collection;
import java.util.List;
-import java.util.Objects;
import net.bytebuddy.ByteBuddy;
@@ -44,6 +43,8 @@
import net.bytebuddy.pool.TypePool;
+import static java.util.Objects.requireNonNull;
+
import static net.bytebuddy.description.modifier.Ownership.STATIC;
import static net.bytebuddy.description.modifier.SyntheticState.SYNTHETIC;
import static net.bytebuddy.description.modifier.Visibility.PRIVATE;
@@ -76,8 +77,8 @@
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
/**
- * An class generator that uses Byte Buddy to {@linkplain #generate(String,
- * TypeDefinition, Collection) generate} {@linkplain org.microbean.reference.ClientProxy client proxy} classes.
+ * A class generator that uses Byte Buddy to {@linkplain #generate(String,
+ * TypeDefinition, Collection) generate} {@linkplain org.microbean.proxy.Proxy client proxy} classes.
*
* @author Laird Nelson
*/
@@ -94,13 +95,13 @@ public final class BBClientProxyClassGenerator {
*/
public BBClientProxyClassGenerator(final TypePool typePool) {
super();
- this.typePool = Objects.requireNonNull(typePool, "typePool");
+ this.typePool = requireNonNull(typePool, "typePool");
}
/**
* Creates and returns a new {@link DynamicType.Unloaded} representing a client proxy class.
*
- * @param name the name of the client proxy class; must not be {@code null}; must be a valid Java class binary
* name
*
@@ -117,9 +118,9 @@ public final DynamicType.Unloaded> generate(final String name,
final TypeDefinition superclass,
final Collection extends TypeDefinition> interfaces) {
- // ClientProxy
- final TypeDescription.Generic clientProxyType =
- parameterizedType(this.typeDescription("org.microbean.reference.ClientProxy"),
+ // Proxy
+ final TypeDescription.Generic proxyType =
+ parameterizedType(this.typeDescription("org.microbean.proxy.Proxy"),
List.of(superclass))
.build();
@@ -129,12 +130,12 @@ public final DynamicType.Unloaded> generate(final String name,
List.of(TypeDescription.Generic.Builder.of(superclass.asGenericType()).asWildcardUpperBound()))
.build();
- // public final class Name extends Superclass implements ClientProxy, Interfaces { /* ... */ }
+ // public /* synthetic */ final class Name extends Superclass implements Proxy, Interfaces { /* ... */ }
DynamicType.Builder> builder = new ByteBuddy()
.subclass(superclass, NO_CONSTRUCTORS)
.merge(List.of(PUBLIC, SYNTHETIC, TypeManifestation.FINAL))
.name(name)
- .implement(clientProxyType)
+ .implement(proxyType)
.implement(interfaces)
// private final Supplier extends Superclass> $proxiedSupplier;
@@ -157,7 +158,7 @@ public final DynamicType.Unloaded> generate(final String name,
.with("proxiedSupplier"))
.andThen(FieldAccessor.ofField("$proxiedSupplier").setsArgumentAt(0)))
- // @Override // ClientProxy
+ // @Override // Proxy
// public final Superclass $proxied() {
// return this.$proxiedSupplier.get();
// }
@@ -166,12 +167,12 @@ public final DynamicType.Unloaded> generate(final String name,
.onField("$proxiedSupplier")
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
- // @Override // ClientProxy
+ // @Override // Proxy
// public final Superclass $cast() {
- // return ClientProxy.super.$cast();
+ // return Proxy.super.$cast();
// }
.defineMethod("$cast", superclass, PUBLIC, SYNTHETIC, MethodManifestation.FINAL)
- .intercept(DefaultMethodCall.prioritize(clientProxyType.asErasure()))
+ .intercept(DefaultMethodCall.prioritize(proxyType.asErasure()))
// Existing/inherited methods; remember that they form a stack, so the last .method() call below should be the
// most specific. See https://bytebuddy.net/#members for details.
@@ -183,7 +184,7 @@ public final DynamicType.Unloaded> generate(final String name,
.method(isBusinessMethod()
.and(not(isJavaDeclaredMethod()
.and(isPackagePrivate()
- .or(hasOnePackagePrivateParameter())))))
+ .or(hasOneOrMorePackagePrivateParameters())))))
.intercept(invokeSelf()
.onMethodCall(invoke(named("$proxied")))
.withAllArguments())
@@ -231,7 +232,7 @@ public final DynamicType.Unloaded> generate(final String name,
*/
- private static final ElementMatcher hasOnePackagePrivateParameter() {
+ private static final ElementMatcher hasOneOrMorePackagePrivateParameters() {
return m -> {
for (final ParameterDescription pd : m.getParameters()) {
if (isPackagePrivate().matches(pd.getType())) {
@@ -249,16 +250,11 @@ private static final ElementMatcher.Junction isBusinessMethod
}
private static final ElementMatcher.Junction isJavaDeclaredMethod() {
- return isDeclaredBy(typeNameStartsWith("java."));
+ return isDeclaredBy(t -> t.getTypeName().startsWith("java."));
}
private final TypeDescription typeDescription(final String canonicalName) {
return this.typePool.describe(canonicalName).resolve();
}
- private static final ElementMatcher typeNameStartsWith(final String prefix) {
- Objects.requireNonNull(prefix, "prefix");
- return t -> t.getTypeName().startsWith(prefix);
- }
-
}
diff --git a/src/main/java/org/microbean/clientproxy/bytebuddy/TypeDefinitions.java b/src/main/java/org/microbean/clientproxy/bytebuddy/TypeDefinitions.java
index 03ff775..294dd8a 100644
--- a/src/main/java/org/microbean/clientproxy/bytebuddy/TypeDefinitions.java
+++ b/src/main/java/org/microbean/clientproxy/bytebuddy/TypeDefinitions.java
@@ -220,7 +220,7 @@ yield parameterizedType(td,
}
private static final boolean generic(final TypeElement te) {
- // Assumes t is thread safe, e.g. supplied via org.microbean.construct.Domain or similar
+ // Assumes te is thread safe, e.g. supplied via org.microbean.construct.Domain or similar
return switch (te.getKind()) {
case CLASS, CONSTRUCTOR, ENUM, INTERFACE, METHOD, RECORD -> !te.getTypeParameters().isEmpty();
default -> false;
diff --git a/src/main/java/org/microbean/clientproxy/bytebuddy/TypeElementTypePool.java b/src/main/java/org/microbean/clientproxy/bytebuddy/TypeElementTypePool.java
index 92e727c..6f2f46d 100644
--- a/src/main/java/org/microbean/clientproxy/bytebuddy/TypeElementTypePool.java
+++ b/src/main/java/org/microbean/clientproxy/bytebuddy/TypeElementTypePool.java
@@ -17,12 +17,14 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
+import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
import javax.lang.model.element.RecordComponentElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
@@ -46,6 +48,8 @@
import org.microbean.construct.vm.Signatures;
import org.microbean.construct.vm.TypeDescriptors;
+import static java.util.Objects.requireNonNull;
+
/**
* A {@link TypePool.Default} that produces {@link net.bytebuddy.description.type.TypeDescription}s from {@code
* javax.lang.model.*} constructs.
@@ -122,7 +126,7 @@ public TypeElementTypePool(final ClassFileVersion classFileVersion,
super(cacheProvider == null ? new TypePool.CacheProvider.Simple() : cacheProvider,
ClassFileLocator.NoOp.INSTANCE, // no locator
TypePool.Default.ReaderMode.FAST); // irrelevant; doesn't read class files
- this.domain = Objects.requireNonNull(domain, "domain");
+ this.domain = requireNonNull(domain, "domain");
this.classFileVersion = classFileVersion == null ? ClassFileVersion.ofThisVm() : classFileVersion;
}
@@ -187,7 +191,7 @@ protected final Resolution doDescribe(final String binaryName) {
// Note that we deliberately and I believe properly do not use the two-argument form of
// domain#typeElement(ModuleElement, CharSequence), since inferring the ModuleElement representing the caller here
// is all but impossible (except for StackWalker).
-
+
// If binaryName is the binary name of a top-level class, this will work just fine because a top level class' binary
// and canonical names are the same, and canonical names are what domain#typeElement(CharSequence) accepts.
TypeElement e = this.domain.typeElement(binaryName);
@@ -275,6 +279,7 @@ private TypeDescription(final Domain domain, final TypeElement e) {
typeVariableAnnotationTokens(e),
typeVariableBoundsAnnotationTokens(e),
annotationTokens(e),
+ moduleToken(domain, e),
fieldTokens(domain, e),
methodTokens(domain, e),
recordComponentTokens(domain, e),
@@ -406,6 +411,28 @@ private static final List methodTokens(final Domain domain, final E
return Collections.unmodifiableList(l);
}
+ private static final ModuleToken moduleToken(final Domain domain, Element e) {
+ while (e != null && e.getKind() != ElementKind.MODULE) {
+ e = e.getEnclosingElement();
+ }
+ if (e == null) {
+ return null;
+ }
+ final ModuleElement m = (ModuleElement)e;
+ // TODO: implement
+ final String name = domain.toString(m.getQualifiedName());
+ final Set packages = Set.copyOf(m.getEnclosedElements()
+ .stream()
+ .map(p -> domain.toString(((PackageElement)p).getQualifiedName()))
+ .toList());
+ final int modifiers = 0; // TODO: not sure what modifiers are expected; looks like maybe just open
+ final String version = null; // ModuleElement does not expose this information
+ final String mainClass = null; // ModuleElement does not expose this information
+
+ // XXX FIXME TODO: finish implementing
+ return null;
+ }
+
private static final List recordComponentTokens(final Domain domain, final Element e) {
final ArrayList l = new ArrayList<>();
for (final Element ee : e.getEnclosedElements()) {
diff --git a/src/main/java/org/microbean/clientproxy/bytebuddy/package-info.java b/src/main/java/org/microbean/clientproxy/bytebuddy/package-info.java
index e0658d0..320bafa 100644
--- a/src/main/java/org/microbean/clientproxy/bytebuddy/package-info.java
+++ b/src/main/java/org/microbean/clientproxy/bytebuddy/package-info.java
@@ -13,7 +13,7 @@
*/
/**
- * Provides classes and interfaces related to implementing {@linkplain org.microbean.reference.ClientProxy client
+ * Provides classes and interfaces related to implementing {@linkplain org.microbean.proxy.Proxy client
* proxies} using Byte Buddy.
*
* @author Laird Nelson
diff --git a/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxier.java b/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxier.java
index fdc061f..90bcc02 100644
--- a/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxier.java
+++ b/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxier.java
@@ -24,37 +24,43 @@
import java.util.Objects;
import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.microbean.attributes.Attributes;
-import org.microbean.bean.AttributedType;
+import org.microbean.assign.AttributedType;
+import org.microbean.assign.Selectable;
+import org.microbean.assign.Selectables;
+
import org.microbean.bean.Bean;
+import org.microbean.bean.BeanQualifiersMatcher;
import org.microbean.bean.BeanTypeList;
+import org.microbean.bean.BeanTypeMatcher;
import org.microbean.bean.BeanTypes;
+import org.microbean.bean.Beans;
import org.microbean.bean.Constant;
import org.microbean.bean.Id;
-import org.microbean.bean.Request;
-import org.microbean.bean.Selectable;
import org.microbean.bean.IdMatcher;
-import org.microbean.bean.BeanTypeMatcher;
-import org.microbean.bean.InterceptorBindingsMatcher;
-import org.microbean.bean.BeanQualifiersMatcher;
-import org.microbean.bean.Reducer;
-import org.microbean.bean.RankedReducer;
-import org.microbean.bean.Reducible;
+import org.microbean.bean.Qualifiers;
import org.microbean.construct.DefaultDomain;
import org.microbean.construct.Domain;
-import org.microbean.reference.ClientProxy;
-import org.microbean.reference.DefaultRequest;
+import org.microbean.producer.InterceptorBindingsMatcher;
+
+import org.microbean.proxy.Proxy;
+
+import org.microbean.reference.Instances;
+import org.microbean.reference.Request;
import org.microbean.scopelet.MapBackedScopelet;
import org.microbean.scopelet.NoneScopelet;
import org.microbean.scopelet.ScopedInstances;
import org.microbean.scopelet.Scopelet;
+import org.microbean.scopelet.Scopes;
import org.microbean.scopelet.SingletonScopelet;
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
@@ -66,24 +72,20 @@
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.microbean.assign.Qualifiers.anyQualifier;
-import static org.microbean.assign.Qualifiers.anyAndDefaultQualifiers;
-import static org.microbean.assign.Qualifiers.defaultQualifier;
-import static org.microbean.assign.Qualifiers.defaultQualifiers;
-import static org.microbean.assign.Qualifiers.qualifier;
-
-import static org.microbean.bean.Beans.cachingSelectableOf;
-
-import static org.microbean.scopelet.Scopelet.APPLICATION_ID;
-import static org.microbean.scopelet.Scopelet.NONE_ID;
-import static org.microbean.scopelet.Scopelet.SCOPE;
-import static org.microbean.scopelet.Scopelet.SINGLETON_ID;
+import static org.microbean.bean.Selectables.ambiguityReducing;
+import static org.microbean.bean.Selectables.typesafeFiltering;
final class TestBBClientProxier {
private Domain domain;
- private Request> r;
+ private Qualifiers qualifiers;
+
+ private Request r;
+
+ private Instances instances;
+
+ private Bean> gorpBean;
private TestBBClientProxier() {
super();
@@ -93,44 +95,111 @@ private TestBBClientProxier() {
final void setup() {
this.domain = new DefaultDomain();
- // Rule: your parent scope goes on the Any qualifier
- final Attributes anyQualifierWithSingletonParentScope = Attributes.of("Any", qualifier(), SINGLETON_ID);
final BeanTypes beanTypes = new BeanTypes(domain);
+
+ this.qualifiers = new Qualifiers();
+
+ final Scopes scopes = new Scopes(qualifiers);
+
+ // TODO: all this scopelet tunneling stuff is a specific instance of a general case that is already handle-able. If
+ // you conceive of a Factory that can "create" (cache and return) all kinds of objects, and can use this tunneling
+ // mechanism to look it up, then you don't need a Scopelet type.
+
+ // Rule: your parent scope goes on the Any qualifier. All beans have the Any qualifier (normally) so this is a
+ // convenient way to "tunnel" a qualifier/scope without screwing up typesafe resolution and without requiring
+ // something stupid like BeanAttributes in CDI. You just add meta-annotations.
+ final Attributes anyQualifierWithSingletonParentScope = Attributes.of("Any", qualifiers.qualifier(), scopes.singleton());
+
+ final Bean> domainBean =
+ new Bean<>(new Id(beanTypes.beanTypes(domain.declaredType(DefaultDomain.class.getCanonicalName())),
+ List.of(anyQualifierWithSingletonParentScope, qualifiers.defaultQualifier())),
+ c -> domain);
+
+ final Bean> beanTypesBean =
+ new Bean<>(new Id(beanTypes.beanTypes(domain.declaredType(BeanTypes.class.getCanonicalName())),
+ List.of(anyQualifierWithSingletonParentScope, qualifiers.defaultQualifier())),
+ c -> beanTypes);
+
+ // TODO: we should do this for all the matchers, too, e.g. BeanTypeMatcher, BeanQualifiersMatcher,
+ // EventTypesMatcher, etc. etc.
+ //
+ // BBClientProxier too
+ //
+ // Then all these handcrafted beans could say what they need as dependencies and assign them
+
+ final Attributes application =
+ Attributes.of("Application",
+ scopes.normal(),
+ Map.of(),
+ Map.of("Application",
+ List.of(qualifiers.qualifier(),
+ scopes.scope(),
+ scopes.singleton())));
+
+ // Set up scopes.
final Bean> applicationAndSingletonScopeletBean =
new Bean<>(new Id(beanTypes.beanTypes(domain.declaredType(SingletonScopelet.class.getCanonicalName())),
- // Rule: APPLICATION_ID and SINGLETON_ID function here as qualifiers
- List.of(anyQualifierWithSingletonParentScope, APPLICATION_ID, SINGLETON_ID)),
- new SingletonScopelet(domain));
+ // Rule: application and scopes.singleton() function here as qualifiers
+ List.of(anyQualifierWithSingletonParentScope, application, scopes.singleton())),
+ new SingletonScopelet());
+
final Bean> noneScopeletBean =
new Bean<>(new Id(beanTypes.beanTypes(domain.declaredType(NoneScopelet.class.getCanonicalName())),
// Rule: NONE_ID functions here as a qualifier
- List.of(anyQualifierWithSingletonParentScope, NONE_ID)),
- new NoneScopelet(domain));
-
- final Selectable> selectable =
- cachingSelectableOf(List.of(noneScopeletBean,
- applicationAndSingletonScopeletBean,
- new Bean<>(new Id(new BeanTypes(domain).beanTypes(domain.declaredType(Gorp.class.getCanonicalName())),
- List.of(Attributes.of("Any", qualifier(), APPLICATION_ID), defaultQualifier())),
- r -> new Gorp())),
- new IdMatcher(new BeanQualifiersMatcher(),
- new InterceptorBindingsMatcher(),
- new BeanTypeMatcher(domain)),
- Map.of());
+ List.of(anyQualifierWithSingletonParentScope, scopes.none())),
+ new NoneScopelet());
+
+ // Set up the user-supplied bean. Note that it is in application scope.
+ this.gorpBean =
+ new Bean<>(new Id(new BeanTypes(domain).beanTypes(domain.declaredType(Gorp.class.getCanonicalName())),
+ List.of(Attributes.of("Any", qualifiers.qualifier(), application), qualifiers.defaultQualifier())),
+ c -> new Gorp());
+
+ // In a production version of all this we need to allow for supplying a preinitialized selection cache. We will
+ // supply an empty one.
+ final Map>> selectionCache = new ConcurrentHashMap<>();
+
+ // See https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#unsatisfied_and_ambig_dependencies
+ Selectable> selectable =
+ ScopedInstances.selectableOf(domain,
+ Selectables.>caching(ambiguityReducing(typesafeFiltering(List.of(domainBean,
+ beanTypesBean,
+ noneScopeletBean,
+ applicationAndSingletonScopeletBean,
+ this.gorpBean),
+ new IdMatcher(new BeanTypeMatcher(domain),
+ new BeanQualifiersMatcher(qualifiers),
+ new InterceptorBindingsMatcher())),
+ org.microbean.bean.Ranked::alternate,
+ org.microbean.bean.Ranked::rank
+ ),
+ selectionCache::computeIfAbsent));
+
+ this.instances = new ScopedInstances(domain, qualifiers, scopes);
this.r =
- new DefaultRequest(selectable,
- ScopedInstances.reducible(domain, selectable),
- new ScopedInstances(domain),
- new BBClientProxier(domain));
+ new Request(this.domain,
+ selectable,
+ this.instances,
+ new BBClientProxier(domain));
+ }
+
+ private static final boolean alternate(final Bean> b) {
+ final Id id = b.id();
+ return false;
+ }
+
+ @Test
+ final void testGorpIsProxiable() {
+ assertTrue(this.instances.proxiable(this.gorpBean.id()));
}
@Test
final void testClientProxySunnyDay() {
- final Gorp g = this.r.reference(new AttributedType(this.domain.declaredType(Gorp.class.getCanonicalName()), defaultQualifiers()));
- assertTrue(g instanceof ClientProxy>, String.valueOf(g));
+ final Gorp g = this.r.reference(new AttributedType(this.domain.declaredType(Gorp.class.getCanonicalName()), qualifiers.defaultQualifiers()));
+ assertTrue(g instanceof Proxy>, String.valueOf(g));
assertTrue(g.getClass().isSynthetic());
@SuppressWarnings("unchecked")
- final Gorp proxied = ((ClientProxy)g).$proxied();
+ final Gorp proxied = ((Proxy)g).$proxied();
assertNotSame(g, proxied);
assertSame(Gorp.class, proxied.getClass());
assertEquals("bar", g.bar());
@@ -148,7 +217,7 @@ static class Gorp implements Frobber {
super();
}
- @Override
+ @Override // Frobber
public String frob() {
return "frob";
}
diff --git a/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxyClassGenerator.java b/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxyClassGenerator.java
index def9bbf..6928ca3 100644
--- a/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxyClassGenerator.java
+++ b/src/test/java/org/microbean/clientproxy/bytebuddy/TestBBClientProxyClassGenerator.java
@@ -37,7 +37,7 @@
import org.microbean.construct.DefaultDomain;
import org.microbean.construct.Domain;
-import org.microbean.reference.ClientProxy;
+import org.microbean.proxy.Proxy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@@ -78,13 +78,13 @@ final void testGenerateSunnyDay() throws IOException, IllegalAccessException, In
final Class> cls = dtl.getLoaded();
assertEquals(proxyClassName, cls.getName());
- assertTrue(ClientProxy.class.isAssignableFrom(cls));
+ assertTrue(Proxy.class.isAssignableFrom(cls));
assertTrue(Gorp.class.isAssignableFrom(cls));
assertTrue(Cloneable.class.isAssignableFrom(cls));
final Constructor> c = cls.getDeclaredConstructor(Supplier.class);
@SuppressWarnings("unchecked")
- final ClientProxy cp = (ClientProxy)c.newInstance(s);
+ final Proxy cp = (Proxy)c.newInstance(s);
assertTrue(cp instanceof Gorp);
assertTrue(cp instanceof Cloneable);