diff --git a/.gitignore b/.gitignore index 530ec7f8c9c3..9544fbceec5e 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,5 @@ cached-antora-playbook.yml node_modules /.kotlin/ +.ai/ +.junie/ diff --git a/build.gradle b/build.gradle index c4ee9d3653b1..2329b8b090d9 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ plugins { ext { moduleProjects = subprojects.findAll { it.name.startsWith("spring-") } javaProjects = subprojects.findAll { !it.name.startsWith("framework-") } + mixinAnnotationVersion = "1.1.18" } description = "Spring Framework" diff --git a/framework-annotation-processor/framework-annotation-processor.gradle b/framework-annotation-processor/framework-annotation-processor.gradle new file mode 100644 index 000000000000..d68d69e097a6 --- /dev/null +++ b/framework-annotation-processor/framework-annotation-processor.gradle @@ -0,0 +1,3 @@ +plugins { + id("java") +} diff --git a/framework-annotation-processor/src/main/java/org/springframework/annotation/processor/NonProcessedAnnotationClaimer.java b/framework-annotation-processor/src/main/java/org/springframework/annotation/processor/NonProcessedAnnotationClaimer.java new file mode 100644 index 000000000000..938f0f1b7d8b --- /dev/null +++ b/framework-annotation-processor/src/main/java/org/springframework/annotation/processor/NonProcessedAnnotationClaimer.java @@ -0,0 +1,93 @@ +package org.springframework.annotation.processor; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import java.util.Set; + +/** + * This annotation processor claims all the annotations that are not processed at compile time at all. + * Otherwise, the compiler would emit a warning that + * {@code No processor claimed any of these annotations}. Adding this to the compiler arg option {@code -Werror}, + * would fail the build. + */ +@SupportedAnnotationTypes({ + "com.fasterxml.jackson.annotation.JsonAnyGetter", + "com.fasterxml.jackson.annotation.JsonAnySetter", + "com.fasterxml.jackson.annotation.JsonInclude", + "com.fasterxml.jackson.annotation.JsonRootName", + "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty", + "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement", + "com.oracle.svm.core.annotate.Alias", + "com.oracle.svm.core.annotate.Substitute", + "com.oracle.svm.core.annotate.TargetClass", + "jakarta.annotation.Generated", + "jakarta.servlet.annotation.HandlesTypes", + "javax.annotation.CheckForNull", + "javax.annotation.Nonnull", + "javax.annotation.meta.TypeQualifierDefault", + "javax.annotation.meta.TypeQualifierNickname", + "jdk.jfr/jdk.jfr.Category", + "jdk.jfr/jdk.jfr.Description", + "jdk.jfr/jdk.jfr.Enabled", + "jdk.jfr/jdk.jfr.Label", + "jdk.jfr/jdk.jfr.Registered", + "jdk.jfr/jdk.jfr.StackTrace", + "org.jspecify.annotations.NullMarked", + "org.jspecify.annotations.NullUnmarked", + "org.springframework.aot.hint.annotation.Reflective", + "org.springframework.aot.hint.annotation.RegisterReflection", + "org.springframework.beans.factory.annotation.Autowired", + "org.springframework.beans.factory.annotation.Qualifier", + "org.springframework.context.annotation.Bean", + "org.springframework.context.annotation.Conditional", + "org.springframework.context.annotation.Configuration", + "org.springframework.context.event.EventListener", + "org.springframework.context.annotation.Import", + "org.springframework.context.annotation.ImportRuntimeHints", + "org.springframework.context.annotation.Lazy", + "org.springframework.context.annotation.Role", + "org.springframework.context.annotation.Scope", + "org.springframework.core.annotation.AliasFor", + "org.springframework.core.annotation.Order", + "org.springframework.lang.CheckReturnValue", + "org.springframework.lang.Contract", + "org.springframework.messaging.handler.annotation.MessageMapping", + "org.springframework.stereotype.Component", + "org.springframework.stereotype.Controller", + "org.springframework.stereotype.Indexed", + "org.junit.jupiter.api.Test", + "org.junit.jupiter.api.BeforeEach", + "org.junit.jupiter.api.AfterEach", + "org.junit.jupiter.api.extension.RegisterExtension", + "org.junit.jupiter.api.extension.ExtendWith", + "org.junit.jupiter.params.ParameterizedTest", + "org.junit.jupiter.params.provider.MethodSource", + "org.springframework.test.annotation.Rollback", + "org.springframework.test.context.ContextConfiguration", + "org.springframework.test.context.bean.override.BeanOverride", + "org.springframework.test.context.web.WebAppConfiguration", + "org.springframework.transaction.annotation.Transactional", + "org.testng.annotations.AfterClass", + "org.testng.annotations.AfterMethod", + "org.testng.annotations.BeforeClass", + "org.testng.annotations.BeforeMethod", + "org.junit.runner.RunWith", + "jakarta.xml.bind.annotation.XmlRootElement", + "org.springframework.web.bind.annotation.ControllerAdvice", + "org.springframework.web.bind.annotation.ExceptionHandler", + "org.springframework.web.bind.annotation.Mapping", + "org.springframework.web.bind.annotation.RequestMapping", + "org.springframework.web.bind.annotation.ResponseBody", + "org.springframework.web.service.annotation.HttpExchange", + "tools.jackson.dataformat.xml.annotation.JacksonXmlProperty", +}) + + +@SupportedSourceVersion(SourceVersion.RELEASE_21) +public class NonProcessedAnnotationClaimer extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return true; + } +} diff --git a/framework-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/framework-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 000000000000..a8be7ed8a8f0 --- /dev/null +++ b/framework-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +org.springframework.annotation.processor.NonProcessedAnnotationClaimer \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 052b11485e89..e45ea83ec85d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,7 @@ include "framework-api" include "framework-bom" include "framework-docs" include "framework-platform" +include 'framework-annotation-processor' include "integration-tests" rootProject.name = "spring" @@ -50,3 +51,4 @@ settings.gradle.projectsLoaded { } } } + diff --git a/spring-beans/spring-beans.gradle b/spring-beans/spring-beans.gradle index a725741630b2..20617727eb42 100644 --- a/spring-beans/spring-beans.gradle +++ b/spring-beans/spring-beans.gradle @@ -3,8 +3,11 @@ description = "Spring Beans" apply plugin: "kotlin" dependencies { + annotationProcessor project(":framework-annotation-processor") api(project(":spring-core")) - optional("jakarta.inject:jakarta.inject-api") + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + optional("jakarta.inject:jakarta.inject-api") optional("org.apache.groovy:groovy-xml") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index cba10a190431..605e4d126d92 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -16,10 +16,7 @@ package org.springframework.beans; -import java.awt.Image; -import java.beans.BeanDescriptor; import java.beans.BeanInfo; -import java.beans.EventSetDescriptor; import java.beans.IndexedPropertyDescriptor; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -34,6 +31,7 @@ import java.util.Set; import java.util.TreeSet; +import guru.mocker.annotation.mixin.Mixin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; @@ -78,12 +76,11 @@ * @see ExtendedBeanInfoFactory * @see CachedIntrospectionResults */ -class ExtendedBeanInfo implements BeanInfo { +@Mixin +class ExtendedBeanInfo extends ExtendedBeanInfoForwarder implements BeanInfo { private static final Log logger = LogFactory.getLog(ExtendedBeanInfo.class); - private final BeanInfo delegate; - private final Set propertyDescriptors = new TreeSet<>(new PropertyDescriptorComparator()); @@ -98,7 +95,7 @@ class ExtendedBeanInfo implements BeanInfo { * @see #getPropertyDescriptors() */ public ExtendedBeanInfo(BeanInfo delegate) { - this.delegate = delegate; + super(delegate); for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) { try { this.propertyDescriptors.add(pd instanceof IndexedPropertyDescriptor indexedPd ? @@ -223,42 +220,6 @@ public PropertyDescriptor[] getPropertyDescriptors() { return this.propertyDescriptors.toArray(PropertyDescriptorUtils.EMPTY_PROPERTY_DESCRIPTOR_ARRAY); } - @Override - public BeanInfo[] getAdditionalBeanInfo() { - return this.delegate.getAdditionalBeanInfo(); - } - - @Override - public BeanDescriptor getBeanDescriptor() { - return this.delegate.getBeanDescriptor(); - } - - @Override - public int getDefaultEventIndex() { - return this.delegate.getDefaultEventIndex(); - } - - @Override - public int getDefaultPropertyIndex() { - return this.delegate.getDefaultPropertyIndex(); - } - - @Override - public EventSetDescriptor[] getEventSetDescriptors() { - return this.delegate.getEventSetDescriptors(); - } - - @Override - public Image getIcon(int iconKind) { - return this.delegate.getIcon(iconKind); - } - - @Override - public MethodDescriptor[] getMethodDescriptors() { - return this.delegate.getMethodDescriptors(); - } - - /** * A simple {@link PropertyDescriptor}. */ diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java index 37e8c50e0040..825f43d7b9e3 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java @@ -16,17 +16,10 @@ package org.springframework.beans.factory.aot; -import java.util.List; -import java.util.function.Predicate; import java.util.function.UnaryOperator; -import org.springframework.aot.generate.GenerationContext; -import org.springframework.aot.generate.MethodReference; -import org.springframework.beans.factory.support.RegisteredBean; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.ResolvableType; -import org.springframework.javapoet.ClassName; -import org.springframework.javapoet.CodeBlock; +import guru.mocker.annotation.mixin.Mixin; + import org.springframework.util.Assert; /** @@ -39,60 +32,12 @@ * @author Stephane Nicoll * @since 6.0 */ -public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationCodeFragments { - - private final BeanRegistrationCodeFragments delegate; - +@Mixin +public class BeanRegistrationCodeFragmentsDecorator extends BeanRegistrationCodeFragmentsForwarder implements BeanRegistrationCodeFragments { protected BeanRegistrationCodeFragmentsDecorator(BeanRegistrationCodeFragments delegate) { + super(delegate); Assert.notNull(delegate, "Delegate must not be null"); - this.delegate = delegate; - } - - @Override - public ClassName getTarget(RegisteredBean registeredBean) { - return this.delegate.getTarget(registeredBean); - } - - @Override - public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, - ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { - - return this.delegate.generateNewBeanDefinitionCode(generationContext, beanType, beanRegistrationCode); - } - - @Override - public CodeBlock generateSetBeanDefinitionPropertiesCode( - GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - RootBeanDefinition beanDefinition, Predicate attributeFilter) { - - return this.delegate.generateSetBeanDefinitionPropertiesCode( - generationContext, beanRegistrationCode, beanDefinition, attributeFilter); - } - - @Override - public CodeBlock generateSetBeanInstanceSupplierCode( - GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - CodeBlock instanceSupplierCode, List postProcessors) { - - return this.delegate.generateSetBeanInstanceSupplierCode(generationContext, - beanRegistrationCode, instanceSupplierCode, postProcessors); - } - - @Override - public CodeBlock generateInstanceSupplierCode( - GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - boolean allowDirectSupplierShortcut) { - - return this.delegate.generateInstanceSupplierCode(generationContext, - beanRegistrationCode, allowDirectSupplierShortcut); - } - - @Override - public CodeBlock generateReturnCode( - GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { - - return this.delegate.generateReturnCode(generationContext, beanRegistrationCode); } } diff --git a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java index 04722fe7f7bc..f804e137d17c 100644 --- a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java +++ b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java @@ -22,12 +22,12 @@ import java.util.Map; import java.util.Set; +import guru.mocker.annotation.mixin.Mixin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; import org.springframework.core.SpringProperties; -import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -52,7 +52,7 @@ * @see ConfigurableEnvironment * @see StandardEnvironment */ -public abstract class AbstractEnvironment implements ConfigurableEnvironment { +public abstract class AbstractEnvironment extends AbstractEnvironmentForwarder implements ConfigurableEnvironment { /** * System property that instructs Spring to ignore system environment variables, @@ -61,6 +61,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { * Spring environment property (for example, a placeholder in a configuration String) isn't * resolvable otherwise. Consider switching this flag to "true" if you experience * log warnings from {@code getenv} calls coming from Spring. + * * @see #suppressGetenvAccess() */ public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore"; @@ -72,6 +73,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { * character in variable names. Assuming that Spring's {@link SystemEnvironmentPropertySource} * is in use, this property may be specified as an environment variable named * {@code SPRING_PROFILES_ACTIVE}. + * * @see ConfigurableEnvironment#setActiveProfiles */ public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active"; @@ -83,6 +85,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { * character in variable names. Assuming that Spring's {@link SystemEnvironmentPropertySource} * is in use, this property may be specified as an environment variable named * {@code SPRING_PROFILES_DEFAULT}. + * * @see ConfigurableEnvironment#setDefaultProfiles */ public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default"; @@ -91,6 +94,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { * Name of the reserved default profile name: {@value}. *

If no default profile names are explicitly set and no active profile names * are explicitly set, this profile will automatically be activated by default. + * * @see #getReservedDefaultProfiles * @see ConfigurableEnvironment#setDefaultProfiles * @see ConfigurableEnvironment#setActiveProfiles @@ -108,14 +112,12 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { private final MutablePropertySources propertySources; - private final ConfigurablePropertyResolver propertyResolver; - - /** * Create a new {@code Environment} instance, calling back to * {@link #customizePropertySources(MutablePropertySources)} during construction to * allow subclasses to contribute or manipulate {@link PropertySource} instances as * appropriate. + * * @see #customizePropertySources(MutablePropertySources) */ public AbstractEnvironment() { @@ -128,17 +130,36 @@ public AbstractEnvironment() { * {@link #customizePropertySources(MutablePropertySources)} during * construction to allow subclasses to contribute or manipulate * {@link PropertySource} instances as appropriate. + * * @param propertySources property sources to use * @since 5.3.4 * @see #customizePropertySources(MutablePropertySources) */ protected AbstractEnvironment(MutablePropertySources propertySources) { + this(null, propertySources); + } + + /** + * Constructs a new AbstractEnvironment instance with the specified property sources and property resolver. + * + * @param propertySources the collection of {@code PropertySource} objects to load and manage environment properties. + * @param propertyResolver the resolver to handle property placeholders and resolve their values. + */ + public AbstractEnvironment(MutablePropertySources propertySources, ConfigurablePropertyResolver propertyResolver) { + this(propertyResolver, propertySources); + } + + @Mixin + private AbstractEnvironment( + @Nullable ConfigurablePropertyResolver propertyResolver, + MutablePropertySources propertySources + ) { + super(propertyResolver); this.propertySources = propertySources; - this.propertyResolver = createPropertyResolver(propertySources); + this.propertyResolver = propertyResolver == null ? createPropertyResolver(propertySources) : propertyResolver; customizePropertySources(propertySources); } - /** * Factory method used to create the {@link ConfigurablePropertyResolver} * used by this {@code Environment}. @@ -155,7 +176,7 @@ protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySou * @see #createPropertyResolver(MutablePropertySources) */ protected final ConfigurablePropertyResolver getPropertyResolver() { - return this.propertyResolver; + return propertyResolver; } /** @@ -261,6 +282,21 @@ public String[] getActiveProfiles() { return StringUtils.toStringArray(doGetActiveProfiles()); } + @Override + public void setActiveProfiles(String... profiles) { + Assert.notNull(profiles, "Profile array must not be null"); + if (logger.isDebugEnabled()) { + logger.debug("Activating profiles " + Arrays.toString(profiles)); + } + synchronized (this.activeProfiles) { + this.activeProfiles.clear(); + for (String profile : profiles) { + validateProfile(profile); + this.activeProfiles.add(profile); + } + } + } + /** * Return the set of active profiles as explicitly set through * {@link #setActiveProfiles} or if the current set of active profiles @@ -291,21 +327,6 @@ protected Set doGetActiveProfiles() { return getProperty(ACTIVE_PROFILES_PROPERTY_NAME); } - @Override - public void setActiveProfiles(String... profiles) { - Assert.notNull(profiles, "Profile array must not be null"); - if (logger.isDebugEnabled()) { - logger.debug("Activating profiles " + Arrays.toString(profiles)); - } - synchronized (this.activeProfiles) { - this.activeProfiles.clear(); - for (String profile : profiles) { - validateProfile(profile); - this.activeProfiles.add(profile); - } - } - } - @Override public void addActiveProfile(String profile) { if (logger.isDebugEnabled()) { @@ -323,11 +344,31 @@ public String[] getDefaultProfiles() { return StringUtils.toStringArray(doGetDefaultProfiles()); } + /** + * Specify the set of profiles to be made active by default if no other profiles + * are explicitly made active through {@link #setActiveProfiles}. + *

Calling this method removes overrides any reserved default profiles + * that may have been added during construction of the environment. + * @see #AbstractEnvironment() + * @see #getReservedDefaultProfiles() + */ + @Override + public void setDefaultProfiles(String... profiles) { + Assert.notNull(profiles, "Profile array must not be null"); + synchronized (this.defaultProfiles) { + this.defaultProfiles.clear(); + for (String profile : profiles) { + validateProfile(profile); + this.defaultProfiles.add(profile); + } + } + } + /** * Return the set of default profiles explicitly set via * {@link #setDefaultProfiles(String...)}, or if the current set of default profiles * consists only of {@linkplain #getReservedDefaultProfiles() reserved default - * profiles}, then check for the presence of {@link #doGetDefaultProfilesProperty()} + * profiles}, then check for the presence of {@link #doGetActiveProfilesProperty()} * and assign its value (if any) to the set of default profiles. * @see #AbstractEnvironment() * @see #getDefaultProfiles() @@ -356,26 +397,6 @@ protected Set doGetDefaultProfiles() { return getProperty(DEFAULT_PROFILES_PROPERTY_NAME); } - /** - * Specify the set of profiles to be made active by default if no other profiles - * are explicitly made active through {@link #setActiveProfiles}. - *

Calling this method removes overrides any reserved default profiles - * that may have been added during construction of the environment. - * @see #AbstractEnvironment() - * @see #getReservedDefaultProfiles() - */ - @Override - public void setDefaultProfiles(String... profiles) { - Assert.notNull(profiles, "Profile array must not be null"); - synchronized (this.defaultProfiles) { - this.defaultProfiles.clear(); - for (String profile : profiles) { - validateProfile(profile); - this.defaultProfiles.add(profile); - } - } - } - @Override @Deprecated(since = "5.1") public boolean acceptsProfiles(String... profiles) { @@ -416,7 +437,7 @@ protected boolean isProfileActive(String profile) { * active or default profiles. *

Subclasses may override to impose further restrictions on profile syntax. * @throws IllegalArgumentException if the profile is null, empty, whitespace-only or - * begins with the profile NOT operator (!) + * begins with the profile NOT operator (!) * @see #acceptsProfiles * @see #addActiveProfile * @see #setDefaultProfiles @@ -487,107 +508,6 @@ public void merge(ConfigurableEnvironment parent) { } } - - //--------------------------------------------------------------------- - // Implementation of ConfigurablePropertyResolver interface - //--------------------------------------------------------------------- - - @Override - public ConfigurableConversionService getConversionService() { - return this.propertyResolver.getConversionService(); - } - - @Override - public void setConversionService(ConfigurableConversionService conversionService) { - this.propertyResolver.setConversionService(conversionService); - } - - @Override - public void setPlaceholderPrefix(String placeholderPrefix) { - this.propertyResolver.setPlaceholderPrefix(placeholderPrefix); - } - - @Override - public void setPlaceholderSuffix(String placeholderSuffix) { - this.propertyResolver.setPlaceholderSuffix(placeholderSuffix); - } - - @Override - public void setValueSeparator(@Nullable String valueSeparator) { - this.propertyResolver.setValueSeparator(valueSeparator); - } - - @Override - public void setEscapeCharacter(@Nullable Character escapeCharacter) { - this.propertyResolver.setEscapeCharacter(escapeCharacter); - } - - @Override - public void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders) { - this.propertyResolver.setIgnoreUnresolvableNestedPlaceholders(ignoreUnresolvableNestedPlaceholders); - } - - @Override - public void setRequiredProperties(String... requiredProperties) { - this.propertyResolver.setRequiredProperties(requiredProperties); - } - - @Override - public void validateRequiredProperties() throws MissingRequiredPropertiesException { - this.propertyResolver.validateRequiredProperties(); - } - - - //--------------------------------------------------------------------- - // Implementation of PropertyResolver interface - //--------------------------------------------------------------------- - - @Override - public boolean containsProperty(String key) { - return this.propertyResolver.containsProperty(key); - } - - @Override - public @Nullable String getProperty(String key) { - return this.propertyResolver.getProperty(key); - } - - @Override - public String getProperty(String key, String defaultValue) { - return this.propertyResolver.getProperty(key, defaultValue); - } - - @Override - public @Nullable T getProperty(String key, Class targetType) { - return this.propertyResolver.getProperty(key, targetType); - } - - @Override - public T getProperty(String key, Class targetType, T defaultValue) { - return this.propertyResolver.getProperty(key, targetType, defaultValue); - } - - @Override - public String getRequiredProperty(String key) throws IllegalStateException { - return this.propertyResolver.getRequiredProperty(key); - } - - @Override - public T getRequiredProperty(String key, Class targetType) throws IllegalStateException { - return this.propertyResolver.getRequiredProperty(key, targetType); - } - - @Override - public String resolvePlaceholders(String text) { - return this.propertyResolver.resolvePlaceholders(text); - } - - @Override - public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException { - return this.propertyResolver.resolveRequiredPlaceholders(text); - } - - @Override public String toString() { return getClass().getSimpleName() + " {activeProfiles=" + this.activeProfiles + diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBuffer.java b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBuffer.java index 609c954e85cf..cf87ca4d9360 100644 --- a/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBuffer.java +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBuffer.java @@ -16,337 +16,94 @@ package org.springframework.core.io.buffer; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.IntPredicate; - +import guru.mocker.annotation.mixin.Mixin; import org.eclipse.jetty.io.Content; -import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; /** - * Implementation of the {@code DataBuffer} interface that can wrap a Jetty - * {@link Content.Chunk}. Typically constructed with {@link JettyDataBufferFactory}. + * Implementation of the {@code DataBuffer} interface that can wrap a Jetty {@link Content.Chunk}. Typically constructed + * with {@link JettyDataBufferFactory}. * * @author Greg Wilkins * @author Lachlan Roberts * @author Arjen Poutsma * @since 6.2 */ -public final class JettyDataBuffer implements PooledDataBuffer { - - private final DefaultDataBuffer delegate; - - private final Content.@Nullable Chunk chunk; +public final class JettyDataBuffer extends JettyVirtualDataBuffer { - private final JettyDataBufferFactory bufferFactory; + private final Content.Chunk chunk; - private final AtomicInteger refCount = new AtomicInteger(1); + JettyDataBuffer(JettyDataBufferFactory bufferFactory, DataBuffer delegate, Content.Chunk chunk) { + super(bufferFactory, delegate); - - JettyDataBuffer(JettyDataBufferFactory bufferFactory, DefaultDataBuffer delegate, Content.Chunk chunk) { - Assert.notNull(bufferFactory, "BufferFactory must not be null"); - Assert.notNull(delegate, "Delegate must not be null"); Assert.notNull(chunk, "Chunk must not be null"); - this.bufferFactory = bufferFactory; - this.delegate = delegate; this.chunk = chunk; } - JettyDataBuffer(JettyDataBufferFactory bufferFactory, DefaultDataBuffer delegate) { - Assert.notNull(bufferFactory, "BufferFactory must not be null"); - Assert.notNull(delegate, "Delegate must not be null"); - - this.bufferFactory = bufferFactory; - this.delegate = delegate; - this.chunk = null; - } - - - @Override - public boolean isAllocated() { - return this.refCount.get() > 0; - } - @Override public PooledDataBuffer retain() { - int result = this.refCount.updateAndGet(c -> (c != 0 ? c + 1 : 0)); - if (result != 0 && this.chunk != null) { + int result = incrementRefCount(); + if (result != 0) { this.chunk.retain(); } return this; } - @Override - public PooledDataBuffer touch(Object hint) { - return this; - } - @Override public boolean release() { - int result = this.refCount.updateAndGet(c -> { - if (c != 0) { - return c - 1; - } - else { - throw new IllegalStateException("JettyDataBuffer already released: " + this); - } - }); - if (this.chunk != null) { - return this.chunk.release(); - } - else { - return (result == 0); - } - } - - @Override - public DataBufferFactory factory() { - return this.bufferFactory; - } - - - // delegation - - @Override - public int indexOf(IntPredicate predicate, int fromIndex) { - return this.delegate.indexOf(predicate, fromIndex); - } - - @Override - public int lastIndexOf(IntPredicate predicate, int fromIndex) { - return this.delegate.lastIndexOf(predicate, fromIndex); - } - - @Override - public int readableByteCount() { - return this.delegate.readableByteCount(); - } - - @Override - public int writableByteCount() { - return this.delegate.writableByteCount(); - } - - @Override - public int capacity() { - return this.delegate.capacity(); - } - - @Override - @Deprecated(since = "6.0") - public DataBuffer capacity(int capacity) { - this.delegate.capacity(capacity); - return this; - } - - @Override - public DataBuffer ensureWritable(int capacity) { - this.delegate.ensureWritable(capacity); - return this; - } - - @Override - public int readPosition() { - return this.delegate.readPosition(); - } - - @Override - public DataBuffer readPosition(int readPosition) { - this.delegate.readPosition(readPosition); - return this; - } - - @Override - public int writePosition() { - return this.delegate.writePosition(); - } - - @Override - public DataBuffer writePosition(int writePosition) { - this.delegate.writePosition(writePosition); - return this; - } - - @Override - public byte getByte(int index) { - return this.delegate.getByte(index); - } - - @Override - public byte read() { - return this.delegate.read(); - } - - @Override - public DataBuffer read(byte[] destination) { - this.delegate.read(destination); - return this; - } - - @Override - public DataBuffer read(byte[] destination, int offset, int length) { - this.delegate.read(destination, offset, length); - return this; - } - - @Override - public DataBuffer write(byte b) { - this.delegate.write(b); - return this; - } - - @Override - public DataBuffer write(byte[] source) { - this.delegate.write(source); - return this; - } - - @Override - public DataBuffer write(byte[] source, int offset, int length) { - this.delegate.write(source, offset, length); - return this; - } - - @Override - public DataBuffer write(DataBuffer... buffers) { - this.delegate.write(buffers); - return this; - } - - @Override - public DataBuffer write(ByteBuffer... buffers) { - this.delegate.write(buffers); - return this; + decrementRefCount(); + return this.chunk.release(); } @Override @Deprecated(since = "6.0") public DataBuffer slice(int index, int length) { - DefaultDataBuffer delegateSlice = this.delegate.slice(index, length); - if (this.chunk != null) { - this.chunk.retain(); - return new JettyDataBuffer(this.bufferFactory, delegateSlice, this.chunk); - } - else { - return new JettyDataBuffer(this.bufferFactory, delegateSlice); - } + DataBuffer delegateSlice = super.slice(index, length); + this.chunk.retain(); + return new JettyDataBuffer(this.bufferFactory, delegateSlice, this.chunk); } @Override - public DataBuffer split(int index) { - DefaultDataBuffer delegateSplit = this.delegate.split(index); - if (this.chunk != null) { - this.chunk.retain(); - return new JettyDataBuffer(this.bufferFactory, delegateSplit, this.chunk); - } - else { - return new JettyDataBuffer(this.bufferFactory, delegateSplit); - } + public JettyVirtualDataBuffer split(int index) { + DataBuffer delegateSplit = super.split(index); + this.chunk.retain(); + return new JettyDataBuffer(this.bufferFactory, delegateSplit, this.chunk); } - @Override - @Deprecated(since = "6.0") - public ByteBuffer asByteBuffer() { - return this.delegate.asByteBuffer(); - } - - @Override - @Deprecated(since = "6.0") - public ByteBuffer asByteBuffer(int index, int length) { - return this.delegate.asByteBuffer(index, length); - } - - @Override - @Deprecated(since = "6.0.5") - public ByteBuffer toByteBuffer(int index, int length) { - return this.delegate.toByteBuffer(index, length); - } - - @Override - public void toByteBuffer(int srcPos, ByteBuffer dest, int destPos, int length) { - this.delegate.toByteBuffer(srcPos, dest, destPos, length); - } @Override public ByteBufferIterator readableByteBuffers() { - ByteBufferIterator delegateIterator = this.delegate.readableByteBuffers(); - if (this.chunk != null) { - return new JettyByteBufferIterator(delegateIterator, this.chunk); - } - else { - return delegateIterator; - } + ByteBufferIterator delegateIterator = super.readableByteBuffers(); + return new JettyByteBufferIterator(delegateIterator, this.chunk); } @Override public ByteBufferIterator writableByteBuffers() { - ByteBufferIterator delegateIterator = this.delegate.writableByteBuffers(); - if (this.chunk != null) { - return new JettyByteBufferIterator(delegateIterator, this.chunk); - } - else { - return delegateIterator; - } - } - - @Override - public String toString(int index, int length, Charset charset) { - return this.delegate.toString(index, length, charset); - } - - - @Override - public boolean equals(@Nullable Object other) { - return (this == other || (other instanceof JettyDataBuffer otherBuffer && - this.delegate.equals(otherBuffer.delegate))); - } - - @Override - public int hashCode() { - return this.delegate.hashCode(); - } - - @Override - public String toString() { - return String.format("JettyDataBuffer (r: %d, w: %d, c: %d)", - readPosition(), writePosition(), capacity()); + ByteBufferIterator delegateIterator = super.writableByteBuffers(); + return new JettyByteBufferIterator(delegateIterator, this.chunk); } + @Mixin + protected static final class JettyByteBufferIterator extends ByteBufferIteratorForwarder implements ByteBufferIterator { - private static final class JettyByteBufferIterator implements ByteBufferIterator { - - private final ByteBufferIterator delegate; private final Content.Chunk chunk; public JettyByteBufferIterator(ByteBufferIterator delegate, Content.Chunk chunk) { + super(delegate); Assert.notNull(delegate, "Delegate must not be null"); Assert.notNull(chunk, "Chunk must not be null"); - this.delegate = delegate; this.chunk = chunk; this.chunk.retain(); } @Override public void close() { - this.delegate.close(); + super.close(); this.chunk.release(); } - - @Override - public boolean hasNext() { - return this.delegate.hasNext(); - } - - @Override - public ByteBuffer next() { - return this.delegate.next(); - } } - } diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBufferFactory.java b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBufferFactory.java index 502a5c21ebd3..e7f6854e1737 100644 --- a/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBufferFactory.java +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyDataBufferFactory.java @@ -66,27 +66,27 @@ public JettyDataBufferFactory(boolean preferDirect, int defaultInitialCapacity) @Override @Deprecated(since = "6.0") - public JettyDataBuffer allocateBuffer() { + public DataBuffer allocateBuffer() { DefaultDataBuffer delegate = this.delegate.allocateBuffer(); - return new JettyDataBuffer(this, delegate); + return new JettyVirtualDataBuffer(this, delegate); } @Override - public JettyDataBuffer allocateBuffer(int initialCapacity) { + public DataBuffer allocateBuffer(int initialCapacity) { DefaultDataBuffer delegate = this.delegate.allocateBuffer(initialCapacity); - return new JettyDataBuffer(this, delegate); + return new JettyVirtualDataBuffer(this, delegate); } @Override - public JettyDataBuffer wrap(ByteBuffer byteBuffer) { + public DataBuffer wrap(ByteBuffer byteBuffer) { DefaultDataBuffer delegate = this.delegate.wrap(byteBuffer); - return new JettyDataBuffer(this, delegate); + return new JettyVirtualDataBuffer(this, delegate); } @Override - public JettyDataBuffer wrap(byte[] bytes) { + public DataBuffer wrap(byte[] bytes) { DefaultDataBuffer delegate = this.delegate.wrap(bytes); - return new JettyDataBuffer(this, delegate); + return new JettyVirtualDataBuffer(this, delegate); } public JettyDataBuffer wrap(Content.Chunk chunk) { @@ -96,9 +96,9 @@ public JettyDataBuffer wrap(Content.Chunk chunk) { } @Override - public JettyDataBuffer join(List dataBuffers) { + public DataBuffer join(List dataBuffers) { DefaultDataBuffer delegate = this.delegate.join(dataBuffers); - return new JettyDataBuffer(this, delegate); + return new JettyVirtualDataBuffer(this, delegate); } @Override diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/JettyVirtualDataBuffer.java b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyVirtualDataBuffer.java new file mode 100644 index 000000000000..006cf3647189 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/JettyVirtualDataBuffer.java @@ -0,0 +1,139 @@ +/* + * Copyright 2002-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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.core.io.buffer; + +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicInteger; + +import guru.mocker.annotation.mixin.Mixin; +import org.jspecify.annotations.Nullable; + +import org.springframework.util.Assert; + +@Mixin +public sealed class JettyVirtualDataBuffer extends JettyVirtualDataBufferForwarder implements PooledDataBuffer permits JettyDataBuffer { + + final JettyDataBufferFactory bufferFactory; + final DataBuffer delegate; + private final AtomicInteger refCount = new AtomicInteger(1); + + JettyVirtualDataBuffer(JettyDataBufferFactory bufferFactory, DataBuffer delegate) { + super(bufferFactory, delegate); + Assert.notNull(delegate, "Delegate must not be null"); + + this.delegate = delegate; + this.bufferFactory = bufferFactory; + } + + // delegation + @Override + public boolean isAllocated() { + return this.refCount.get() > 0; + } + + @Override + public PooledDataBuffer retain() { + incrementRefCount(); + return this; + } + + int incrementRefCount() { + return this.refCount.updateAndGet(c -> (c != 0 ? c + 1 : 0)); + } + + @Override + public PooledDataBuffer touch(Object hint) { + return this; + } + + @Override + public boolean release() { + int result = decrementRefCount(); + return (result == 0); + } + + int decrementRefCount() { + return this.refCount.updateAndGet(c -> { + if (c != 0) { + return c - 1; + } + else { + throw new IllegalStateException("JettyDataBuffer already released: " + this); + } + }); + } + + @Override + public DataBufferFactory factory() { + return this.bufferFactory; + } + + @Override + @Deprecated(since = "6.0") + public DataBuffer capacity(int capacity) { + this.delegate.capacity(capacity); + return this; + } + + @Override + @Deprecated(since = "6.0") + public DataBuffer slice(int index, int length) { + DataBuffer delegateSlice = this.delegate.slice(index, length); + return new JettyVirtualDataBuffer(this.bufferFactory, delegateSlice); + } + + @Override + public JettyVirtualDataBuffer split(int index) { + DataBuffer delegateSplit = this.delegate.split(index); + return new JettyVirtualDataBuffer(this.bufferFactory, delegateSplit); + } + + @Override + @Deprecated(since = "6.0") + public ByteBuffer asByteBuffer() { + return this.delegate.asByteBuffer(); + } + + @Override + @Deprecated(since = "6.0") + public ByteBuffer asByteBuffer(int index, int length) { + return this.delegate.asByteBuffer(index, length); + } + + @Override + @Deprecated(since = "6.0.5") + public ByteBuffer toByteBuffer(int index, int length) { + return this.delegate.toByteBuffer(index, length); + } + + @Override + public int hashCode() { + return this.delegate.hashCode(); + } + + @Override + public boolean equals(@Nullable Object other) { + return (this == other || (other instanceof JettyVirtualDataBuffer otherBuffer && + this.delegate.equals(otherBuffer.delegate))); + } + + @Override + public String toString() { + return String.format("JettyDataBuffer (r: %d, w: %d, c: %d)", + readPosition(), writePosition(), capacity()); + } +} diff --git a/spring-core/src/main/java/org/springframework/core/log/LogAccessor.java b/spring-core/src/main/java/org/springframework/core/log/LogAccessor.java index 571504560e2e..67d475b2fe89 100644 --- a/spring-core/src/main/java/org/springframework/core/log/LogAccessor.java +++ b/spring-core/src/main/java/org/springframework/core/log/LogAccessor.java @@ -18,6 +18,7 @@ import java.util.function.Supplier; +import guru.mocker.annotation.mixin.Mixin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,18 +30,16 @@ * @author Juergen Hoeller * @since 5.2 */ -public class LogAccessor { - - private final Log log; - +public class LogAccessor extends LogAccessorForwarder { /** * Create a new accessor for the given Commons Log. * @see LogFactory#getLog(Class) * @see LogFactory#getLog(String) */ + @Mixin public LogAccessor(Log log) { - this.log = log; + super(log); } /** @@ -48,7 +47,7 @@ public LogAccessor(Log log) { * @see LogFactory#getLog(Class) */ public LogAccessor(Class logCategory) { - this.log = LogFactory.getLog(logCategory); + this(LogFactory.getLog(logCategory)); } /** @@ -56,168 +55,16 @@ public LogAccessor(Class logCategory) { * @see LogFactory#getLog(String) */ public LogAccessor(String logCategory) { - this.log = LogFactory.getLog(logCategory); + this(LogFactory.getLog(logCategory)); } - /** * Return the target Commons Log. */ public final Log getLog() { - return this.log; - } - - - // Log level checks - - /** - * Is fatal logging currently enabled? - */ - public boolean isFatalEnabled() { - return this.log.isFatalEnabled(); - } - - /** - * Is error logging currently enabled? - */ - public boolean isErrorEnabled() { - return this.log.isErrorEnabled(); - } - - /** - * Is warn logging currently enabled? - */ - public boolean isWarnEnabled() { - return this.log.isWarnEnabled(); - } - - /** - * Is info logging currently enabled? - */ - public boolean isInfoEnabled() { - return this.log.isInfoEnabled(); - } - - /** - * Is debug logging currently enabled? - */ - public boolean isDebugEnabled() { - return this.log.isDebugEnabled(); - } - - /** - * Is trace logging currently enabled? - */ - public boolean isTraceEnabled() { - return this.log.isTraceEnabled(); - } - - - // Plain log methods - - /** - * Log a message with fatal log level. - * @param message the message to log - */ - public void fatal(CharSequence message) { - this.log.fatal(message); - } - - /** - * Log an error with fatal log level. - * @param cause the exception to log - * @param message the message to log - */ - public void fatal(Throwable cause, CharSequence message) { - this.log.fatal(message, cause); - } - - /** - * Log a message with error log level. - * @param message the message to log - */ - public void error(CharSequence message) { - this.log.error(message); - } - - /** - * Log an error with error log level. - * @param cause the exception to log - * @param message the message to log - */ - public void error(Throwable cause, CharSequence message) { - this.log.error(message, cause); + return log; } - /** - * Log a message with warn log level. - * @param message the message to log - */ - public void warn(CharSequence message) { - this.log.warn(message); - } - - /** - * Log an error with warn log level. - * @param cause the exception to log - * @param message the message to log - */ - public void warn(Throwable cause, CharSequence message) { - this.log.warn(message, cause); - } - - /** - * Log a message with info log level. - * @param message the message to log - */ - public void info(CharSequence message) { - this.log.info(message); - } - - /** - * Log an error with info log level. - * @param cause the exception to log - * @param message the message to log - */ - public void info(Throwable cause, CharSequence message) { - this.log.info(message, cause); - } - - /** - * Log a message with debug log level. - * @param message the message to log - */ - public void debug(CharSequence message) { - this.log.debug(message); - } - - /** - * Log an error with debug log level. - * @param cause the exception to log - * @param message the message to log - */ - public void debug(Throwable cause, CharSequence message) { - this.log.debug(message, cause); - } - - /** - * Log a message with trace log level. - * @param message the message to log - */ - public void trace(CharSequence message) { - this.log.trace(message); - } - - /** - * Log an error with trace log level. - * @param cause the exception to log - * @param message the message to log - */ - public void trace(Throwable cause, CharSequence message) { - this.log.trace(message, cause); - } - - // Supplier-based log methods /** @@ -225,8 +72,8 @@ public void trace(Throwable cause, CharSequence message) { * @param messageSupplier a lazy supplier for the message to log */ public void fatal(Supplier messageSupplier) { - if (this.log.isFatalEnabled()) { - this.log.fatal(LogMessage.of(messageSupplier)); + if (super.isFatalEnabled()) { + super.fatal(LogMessage.of(messageSupplier)); } } @@ -236,8 +83,8 @@ public void fatal(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void fatal(Throwable cause, Supplier messageSupplier) { - if (this.log.isFatalEnabled()) { - this.log.fatal(LogMessage.of(messageSupplier), cause); + if (super.isFatalEnabled()) { + super.fatal(LogMessage.of(messageSupplier), cause); } } @@ -246,8 +93,8 @@ public void fatal(Throwable cause, Supplier messageSuppl * @param messageSupplier a lazy supplier for the message to log */ public void error(Supplier messageSupplier) { - if (this.log.isErrorEnabled()) { - this.log.error(LogMessage.of(messageSupplier)); + if (super.isErrorEnabled()) { + super.error(LogMessage.of(messageSupplier)); } } @@ -257,8 +104,8 @@ public void error(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void error(Throwable cause, Supplier messageSupplier) { - if (this.log.isErrorEnabled()) { - this.log.error(LogMessage.of(messageSupplier), cause); + if (super.isErrorEnabled()) { + super.error(LogMessage.of(messageSupplier), cause); } } @@ -267,8 +114,8 @@ public void error(Throwable cause, Supplier messageSuppl * @param messageSupplier a lazy supplier for the message to log */ public void warn(Supplier messageSupplier) { - if (this.log.isWarnEnabled()) { - this.log.warn(LogMessage.of(messageSupplier)); + if (super.isWarnEnabled()) { + super.warn(LogMessage.of(messageSupplier)); } } @@ -278,8 +125,8 @@ public void warn(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void warn(Throwable cause, Supplier messageSupplier) { - if (this.log.isWarnEnabled()) { - this.log.warn(LogMessage.of(messageSupplier), cause); + if (super.isWarnEnabled()) { + super.warn(LogMessage.of(messageSupplier), cause); } } @@ -288,8 +135,8 @@ public void warn(Throwable cause, Supplier messageSuppli * @param messageSupplier a lazy supplier for the message to log */ public void info(Supplier messageSupplier) { - if (this.log.isInfoEnabled()) { - this.log.info(LogMessage.of(messageSupplier)); + if (super.isInfoEnabled()) { + super.info(LogMessage.of(messageSupplier)); } } @@ -299,8 +146,8 @@ public void info(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void info(Throwable cause, Supplier messageSupplier) { - if (this.log.isInfoEnabled()) { - this.log.info(LogMessage.of(messageSupplier), cause); + if (super.isInfoEnabled()) { + super.info(LogMessage.of(messageSupplier), cause); } } @@ -309,8 +156,8 @@ public void info(Throwable cause, Supplier messageSuppli * @param messageSupplier a lazy supplier for the message to log */ public void debug(Supplier messageSupplier) { - if (this.log.isDebugEnabled()) { - this.log.debug(LogMessage.of(messageSupplier)); + if (super.isDebugEnabled()) { + super.debug(LogMessage.of(messageSupplier)); } } @@ -320,8 +167,8 @@ public void debug(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void debug(Throwable cause, Supplier messageSupplier) { - if (this.log.isDebugEnabled()) { - this.log.debug(LogMessage.of(messageSupplier), cause); + if (super.isDebugEnabled()) { + super.debug(LogMessage.of(messageSupplier), cause); } } @@ -330,8 +177,8 @@ public void debug(Throwable cause, Supplier messageSuppl * @param messageSupplier a lazy supplier for the message to log */ public void trace(Supplier messageSupplier) { - if (this.log.isTraceEnabled()) { - this.log.trace(LogMessage.of(messageSupplier)); + if (super.isTraceEnabled()) { + super.trace(LogMessage.of(messageSupplier)); } } @@ -341,8 +188,8 @@ public void trace(Supplier messageSupplier) { * @param messageSupplier a lazy supplier for the message to log */ public void trace(Throwable cause, Supplier messageSupplier) { - if (this.log.isTraceEnabled()) { - this.log.trace(LogMessage.of(messageSupplier), cause); + if (super.isTraceEnabled()) { + super.trace(LogMessage.of(messageSupplier), cause); } } diff --git a/spring-core/src/main/java/org/springframework/util/AutoPopulatingList.java b/spring-core/src/main/java/org/springframework/util/AutoPopulatingList.java index 65b407aed8e0..ee9dcdcef100 100644 --- a/spring-core/src/main/java/org/springframework/util/AutoPopulatingList.java +++ b/spring-core/src/main/java/org/springframework/util/AutoPopulatingList.java @@ -21,11 +21,9 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; import java.util.List; -import java.util.ListIterator; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; /** @@ -45,12 +43,12 @@ * @param the element type */ @SuppressWarnings("serial") -public class AutoPopulatingList implements List, Serializable { +public class AutoPopulatingList extends AutoPopulatingListForwarder implements List, Serializable { /** * The {@link List} that all operations are eventually delegated to. */ - private final List backingList; + final List backingList; /** * The {@link ElementFactory} to use to create new {@link List} elements @@ -89,49 +87,15 @@ public AutoPopulatingList(ElementFactory elementFactory) { * Creates a new {@code AutoPopulatingList} that is backed by the supplied {@link List} * and creates new elements on demand using the supplied {@link ElementFactory}. */ + @Mixin public AutoPopulatingList(List backingList, ElementFactory elementFactory) { + super(backingList, elementFactory); Assert.notNull(backingList, "Backing List must not be null"); Assert.notNull(elementFactory, "Element factory must not be null"); this.backingList = backingList; this.elementFactory = elementFactory; } - - @Override - public void add(int index, E element) { - this.backingList.add(index, element); - } - - @Override - public boolean add(E o) { - return this.backingList.add(o); - } - - @Override - public boolean addAll(Collection c) { - return this.backingList.addAll(c); - } - - @Override - public boolean addAll(int index, Collection c) { - return this.backingList.addAll(index, c); - } - - @Override - public void clear() { - this.backingList.clear(); - } - - @Override - public boolean contains(Object o) { - return this.backingList.contains(o); - } - - @Override - public boolean containsAll(Collection c) { - return this.backingList.containsAll(c); - } - /** * Get the element at the supplied index, creating it if there is * no element at that index. @@ -157,82 +121,6 @@ public E get(int index) { return element; } - @Override - public int indexOf(Object o) { - return this.backingList.indexOf(o); - } - - @Override - public boolean isEmpty() { - return this.backingList.isEmpty(); - } - - @Override - public Iterator iterator() { - return this.backingList.iterator(); - } - - @Override - public int lastIndexOf(Object o) { - return this.backingList.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - return this.backingList.listIterator(); - } - - @Override - public ListIterator listIterator(int index) { - return this.backingList.listIterator(index); - } - - @Override - public E remove(int index) { - return this.backingList.remove(index); - } - - @Override - public boolean remove(Object o) { - return this.backingList.remove(o); - } - - @Override - public boolean removeAll(Collection c) { - return this.backingList.removeAll(c); - } - - @Override - public boolean retainAll(Collection c) { - return this.backingList.retainAll(c); - } - - @Override - public E set(int index, E element) { - return this.backingList.set(index, element); - } - - @Override - public int size() { - return this.backingList.size(); - } - - @Override - public List subList(int fromIndex, int toIndex) { - return this.backingList.subList(fromIndex, toIndex); - } - - @Override - public Object[] toArray() { - return this.backingList.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return this.backingList.toArray(a); - } - - @Override public boolean equals(@Nullable Object other) { return this.backingList.equals(other); @@ -243,7 +131,6 @@ public int hashCode() { return this.backingList.hashCode(); } - /** * Factory interface for creating elements for an index-based access * data structure such as a {@link java.util.List}. @@ -262,7 +149,6 @@ public interface ElementFactory { E createElement(int index) throws ElementInstantiationException; } - /** * Exception to be thrown from ElementFactory. */ @@ -277,7 +163,6 @@ public ElementInstantiationException(String message, Throwable cause) { } } - /** * Reflective implementation of the ElementFactory interface, using * {@code Class.getDeclaredConstructor().newInstance()} on a given element class. diff --git a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java index 2a886020c9c2..d0e58a648398 100644 --- a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java @@ -520,11 +520,11 @@ public static MultiValueMap toMultiValueMap(Map> targetM */ @SuppressWarnings("unchecked") public static MultiValueMap unmodifiableMultiValueMap( - MultiValueMap targetMap) { + MultiValueMap targetMap) { Assert.notNull(targetMap, "'targetMap' must not be null"); if (targetMap instanceof UnmodifiableMultiValueMap) { - return (MultiValueMap) targetMap; + return targetMap; } return new UnmodifiableMultiValueMap<>(targetMap); } diff --git a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java index 438acd1d27df..90cbaf4c1db8 100644 --- a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java +++ b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java @@ -18,8 +18,6 @@ import java.io.Serial; import java.io.Serializable; -import java.util.AbstractCollection; -import java.util.AbstractSet; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -27,11 +25,10 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.Spliterator; import java.util.function.BiConsumer; -import java.util.function.Consumer; import java.util.function.Function; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; /** @@ -348,22 +345,11 @@ protected boolean removeEldestEntry(Map.Entry eldest) { } - private class KeySet extends AbstractSet { - - private final Set delegate; + @Mixin + class KeySet extends KeySetForwarder implements Set { KeySet(Set delegate) { - this.delegate = delegate; - } - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean contains(Object o) { - return this.delegate.contains(o); + super(delegate); } @Override @@ -380,35 +366,13 @@ public boolean remove(Object o) { public void clear() { LinkedCaseInsensitiveMap.this.clear(); } - - @Override - public Spliterator spliterator() { - return this.delegate.spliterator(); - } - - @Override - public void forEach(Consumer action) { - this.delegate.forEach(action); - } } - - private class Values extends AbstractCollection { - - private final Collection delegate; + @Mixin + class Values extends ValuesForwarder implements Collection { Values(Collection delegate) { - this.delegate = delegate; - } - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean contains(Object o) { - return this.delegate.contains(o); + super(delegate); } @Override @@ -420,30 +384,13 @@ public Iterator iterator() { public void clear() { LinkedCaseInsensitiveMap.this.clear(); } - - @Override - public Spliterator spliterator() { - return this.delegate.spliterator(); - } - - @Override - public void forEach(Consumer action) { - this.delegate.forEach(action); - } } - - private class EntrySet extends AbstractSet> { - - private final Set> delegate; + @Mixin + class EntrySet extends EntrySetForwarder implements Set> { EntrySet(Set> delegate) { - this.delegate = delegate; - } - - @Override - public int size() { - return this.delegate.size(); + super(delegate); } @Override @@ -480,21 +427,6 @@ public boolean remove(Object o) { LinkedCaseInsensitiveMap.this.remove(key); return true; } - - @Override - public void clear() { - LinkedCaseInsensitiveMap.this.clear(); - } - - @Override - public Spliterator> spliterator() { - return this.delegate.spliterator(); - } - - @Override - public void forEach(Consumer> action) { - this.delegate.forEach(action); - } } diff --git a/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java b/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java index 6db806ba6f0c..bf2ffb0345da 100644 --- a/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java +++ b/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java @@ -18,12 +18,10 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; /** @@ -38,18 +36,16 @@ * @see LinkedMultiValueMap */ @SuppressWarnings("serial") -public class MultiValueMapAdapter implements MultiValueMap, Serializable { - - private final Map> targetMap; - +@Mixin +public class MultiValueMapAdapter extends MapForwarder implements MultiValueMap, Serializable { /** * Wrap the given target {@link Map} as a {@link MultiValueMap} adapter. - * @param targetMap the plain target {@code Map} + * @param mapForwarder the plain target {@code Map} */ - public MultiValueMapAdapter(Map> targetMap) { - Assert.notNull(targetMap, "'targetMap' must not be null"); - this.targetMap = targetMap; + public MultiValueMapAdapter(Map> mapForwarder) { + super(mapForwarder); + Assert.notNull(mapForwarder, "'targetMap' must not be null"); } @@ -57,19 +53,19 @@ public MultiValueMapAdapter(Map> targetMap) { @Override public @Nullable V getFirst(K key) { - List values = this.targetMap.get(key); + List values = this.mapForwarder.get(key); return (!CollectionUtils.isEmpty(values) ? values.get(0) : null); } @Override public void add(K key, @Nullable V value) { - List values = this.targetMap.computeIfAbsent(key, k -> new ArrayList<>(1)); + List values = this.mapForwarder.computeIfAbsent(key, k -> new ArrayList<>(1)); values.add(value); } @Override public void addAll(K key, List values) { - List currentValues = this.targetMap.computeIfAbsent(key, k -> new ArrayList<>(values.size())); + List currentValues = this.mapForwarder.computeIfAbsent(key, k -> new ArrayList<>(values.size())); currentValues.addAll(values); } @@ -82,7 +78,7 @@ public void addAll(MultiValueMap values) { public void set(K key, @Nullable V value) { List values = new ArrayList<>(1); values.add(value); - this.targetMap.put(key, values); + this.mapForwarder.put(key, values); } @Override @@ -92,8 +88,8 @@ public void setAll(Map values) { @Override public Map toSingleValueMap() { - Map singleValueMap = CollectionUtils.newLinkedHashMap(this.targetMap.size()); - this.targetMap.forEach((key, values) -> { + Map singleValueMap = CollectionUtils.newLinkedHashMap(this.mapForwarder.size()); + this.mapForwarder.forEach((key, values) -> { if (!CollectionUtils.isEmpty(values)) { singleValueMap.put(key, values.get(0)); } @@ -104,89 +100,13 @@ public Map toSingleValueMap() { // Map implementation - @Override - public int size() { - return this.targetMap.size(); - } - - @Override - public boolean isEmpty() { - return this.targetMap.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return this.targetMap.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return this.targetMap.containsValue(value); - } - - @Override - public @Nullable List get(Object key) { - return this.targetMap.get(key); - } - - @Override - public @Nullable List put(K key, List value) { - return this.targetMap.put(key, value); - } - - @Override - public @Nullable List putIfAbsent(K key, List value) { - return this.targetMap.putIfAbsent(key, value); - } - - @Override - public @Nullable List remove(Object key) { - return this.targetMap.remove(key); - } - - @Override - public void putAll(Map> map) { - this.targetMap.putAll(map); - } - - @Override - public void clear() { - this.targetMap.clear(); - } - - @Override - public Set keySet() { - return this.targetMap.keySet(); - } - - @Override - public Collection> values() { - return this.targetMap.values(); - } - - @Override - public Set>> entrySet() { - return this.targetMap.entrySet(); - } - - @Override - public void forEach(BiConsumer> action) { - this.targetMap.forEach(action); - } - @Override public boolean equals(@Nullable Object other) { - return (this == other || this.targetMap.equals(other)); + return (this == other || this.mapForwarder.equals(other)); } @Override public int hashCode() { - return this.targetMap.hashCode(); - } - - @Override - public String toString() { - return this.targetMap.toString(); + return this.mapForwarder.hashCode(); } - } diff --git a/spring-core/src/main/java/org/springframework/util/UnmodifiableMultiValueMap.java b/spring-core/src/main/java/org/springframework/util/UnmodifiableMultiValueMap.java index 5ab48e4f0453..099f14465177 100644 --- a/spring-core/src/main/java/org/springframework/util/UnmodifiableMultiValueMap.java +++ b/spring-core/src/main/java/org/springframework/util/UnmodifiableMultiValueMap.java @@ -33,6 +33,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; /** @@ -43,13 +44,11 @@ * @param the key type * @param the value element type */ -final class UnmodifiableMultiValueMap implements MultiValueMap, Serializable { +@Mixin +final class UnmodifiableMultiValueMap extends UnmodifiableMultiValueMapForwarder implements MultiValueMap, Serializable { private static final long serialVersionUID = -8697084563854098920L; - @SuppressWarnings("serial") - private final MultiValueMap delegate; - private transient @Nullable Set keySet; private transient @Nullable Set>> entrySet; @@ -58,69 +57,27 @@ final class UnmodifiableMultiValueMap implements MultiValueMap, Serial @SuppressWarnings("unchecked") - public UnmodifiableMultiValueMap(MultiValueMap delegate) { + public UnmodifiableMultiValueMap(MultiValueMap delegate) { + super(delegate); Assert.notNull(delegate, "Delegate must not be null"); - this.delegate = (MultiValueMap) delegate; } - // delegation - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return this.delegate.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return this.delegate.containsValue(value); - } - @Override public @Nullable List get(Object key) { - List result = this.delegate.get(key); + List result = super.get(key); return (result != null ? Collections.unmodifiableList(result) : null); } - @Override - public @Nullable V getFirst(K key) { - return this.delegate.getFirst(key); - } - @Override public List getOrDefault(Object key, List defaultValue) { - List result = this.delegate.getOrDefault(key, defaultValue); + List result = super.getOrDefault(key, defaultValue); if (result != defaultValue) { result = Collections.unmodifiableList(result); } return result; } - @Override - public void forEach(BiConsumer> action) { - this.delegate.forEach((k, vs) -> action.accept(k, Collections.unmodifiableList(vs))); - } - - @Override - public Map toSingleValueMap() { - return this.delegate.toSingleValueMap(); - } - - @Override - public Map asSingleValueMap() { - return this.delegate.asSingleValueMap(); - } - @Override public boolean equals(@Nullable Object other) { return (this == other || this.delegate.equals(other)); @@ -132,18 +89,17 @@ public int hashCode() { } @Override - public String toString() { - return this.delegate.toString(); + public void forEach(BiConsumer> action) { + super.forEach((k, vs) -> action.accept(k, Collections.unmodifiableList(vs))); } - // lazy init @Override public Set keySet() { Set keySet = this.keySet; if (keySet == null) { - keySet = Collections.unmodifiableSet(this.delegate.keySet()); + keySet = Collections.unmodifiableSet(super.keySet()); this.keySet = keySet; } return keySet; @@ -153,7 +109,7 @@ public Set keySet() { public Set>> entrySet() { Set>> entrySet = this.entrySet; if (entrySet == null) { - entrySet = new UnmodifiableEntrySet<>(this.delegate.entrySet()); + entrySet = new UnmodifiableEntrySet<>(super.entrySet()); this.entrySet = entrySet; } return entrySet; @@ -163,7 +119,7 @@ public Set>> entrySet() { public Collection> values() { Collection> values = this.values; if (values == null) { - values = new UnmodifiableValueCollection<>(this.delegate.values()); + values = new UnmodifiableValueCollection<>(super.values()); this.values = values; } return values; @@ -172,7 +128,7 @@ public Collection> values() { // unsupported @Override - public @Nullable List put(K key, List value) { + public List put(K key, List value) { throw new UnsupportedOperationException(); } @@ -266,44 +222,20 @@ public void clear() { throw new UnsupportedOperationException(); } - - private static class UnmodifiableEntrySet implements Set>>, Serializable { + @Mixin + protected static class UnmodifiableEntrySet extends UnmodifiableEntrySetForwarder implements Set>>, Serializable { private static final long serialVersionUID = 2407578793783925203L; - @SuppressWarnings("serial") - private final Set>> delegate; @SuppressWarnings("unchecked") - public UnmodifiableEntrySet(Set>> delegate) { - this.delegate = (Set>>) delegate; - } - - // delegation - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return this.delegate.contains(o); - } - - @Override - public boolean containsAll(Collection c) { - return this.delegate.containsAll(c); + public UnmodifiableEntrySet(Set>> delegate) { + super(delegate); } @Override public Iterator>> iterator() { - Iterator>> iterator = this.delegate.iterator(); + Iterator>> iterator = super.iterator(); return new Iterator<>() { @Override public boolean hasNext() { @@ -319,14 +251,14 @@ public Entry> next() { @Override public Object[] toArray() { - Object[] result = this.delegate.toArray(); + Object[] result = super.toArray(); filterArray(result); return result; } @Override public T[] toArray(T[] a) { - T[] result = this.delegate.toArray(a); + T[] result = super.toArray(a); filterArray(result); return result; } @@ -342,7 +274,7 @@ private void filterArray(Object[] result) { @Override public void forEach(Consumer>> action) { - this.delegate.forEach(e -> action.accept(new UnmodifiableEntry<>(e))); + super.forEach(e -> action.accept(new UnmodifiableEntry<>(e))); } @Override @@ -357,7 +289,7 @@ public Stream>> parallelStream() { @Override public Spliterator>> spliterator() { - return new UnmodifiableEntrySpliterator<>(this.delegate.spliterator()); + return new UnmodifiableEntrySpliterator<>(super.spliterator()); } @Override @@ -365,14 +297,13 @@ public boolean equals(@Nullable Object other) { return (this == other || other instanceof Set that && size() == that.size() && containsAll(that)); } + /** + * We must override hashCode to ensure checkstyle is not complaining. + * @return the hash code + */ @Override public int hashCode() { - return this.delegate.hashCode(); - } - - @Override - public String toString() { - return this.delegate.toString(); + return super.hashCode(); } // unsupported @@ -515,50 +446,25 @@ public String toString() { } } - - private static class UnmodifiableValueCollection implements Collection>, Serializable { + @Mixin + protected static class UnmodifiableValueCollection extends UnmodifiableValueCollectionForwarder implements Collection>, Serializable { private static final long serialVersionUID = 5518377583904339588L; - @SuppressWarnings("serial") - private final Collection> delegate; - public UnmodifiableValueCollection(Collection> delegate) { - this.delegate = delegate; - } - - // delegation - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return this.delegate.contains(o); - } - - @Override - public boolean containsAll(Collection c) { - return this.delegate.containsAll(c); + super(delegate); } @Override public Object[] toArray() { - Object[] result = this.delegate.toArray(); + Object[] result = super.toArray(); filterArray(result); return result; } @Override public T[] toArray(T[] a) { - T[] result = this.delegate.toArray(a); + T[] result = super.toArray(a); filterArray(result); return result; } @@ -573,7 +479,7 @@ private void filterArray(Object[] array) { @Override public Iterator> iterator() { - Iterator> iterator = this.delegate.iterator(); + Iterator> iterator = super.iterator(); return new Iterator<>() { @Override public boolean hasNext() { @@ -589,12 +495,12 @@ public List next() { @Override public void forEach(Consumer> action) { - this.delegate.forEach(list -> action.accept(Collections.unmodifiableList(list))); + super.forEach(list -> action.accept(Collections.unmodifiableList(list))); } @Override public Spliterator> spliterator() { - return new UnmodifiableValueSpliterator<>(this.delegate.spliterator()); + return new UnmodifiableValueSpliterator<>(super.spliterator()); } @Override @@ -607,21 +513,6 @@ public Stream> parallelStream() { return StreamSupport.stream(spliterator(), true); } - @Override - public boolean equals(@Nullable Object other) { - return (this == other || this.delegate.equals(other)); - } - - @Override - public int hashCode() { - return this.delegate.hashCode(); - } - - @Override - public String toString() { - return this.delegate.toString(); - } - // unsupported @Override @@ -659,28 +550,26 @@ public void clear() { throw new UnsupportedOperationException(); } - - private static class UnmodifiableValueSpliterator implements Spliterator> { - - private final Spliterator> delegate; + @Mixin + protected static class UnmodifiableValueSpliterator extends UnmodifiableValueSpliteratorForwarder implements Spliterator> { public UnmodifiableValueSpliterator(Spliterator> delegate) { - this.delegate = delegate; + super(delegate); } @Override public boolean tryAdvance(Consumer> action) { - return this.delegate.tryAdvance(l -> action.accept(Collections.unmodifiableList(l))); + return super.tryAdvance(l -> action.accept(Collections.unmodifiableList(l))); } @Override public void forEachRemaining(Consumer> action) { - this.delegate.forEachRemaining(l -> action.accept(Collections.unmodifiableList(l))); + super.forEachRemaining(l -> action.accept(Collections.unmodifiableList(l))); } @Override - public @Nullable Spliterator> trySplit() { - Spliterator> split = this.delegate.trySplit(); + public UnmodifiableMultiValueMap.UnmodifiableValueCollection.@Nullable UnmodifiableValueSpliterator trySplit() { + Spliterator> split = super.trySplit(); if (split != null) { return new UnmodifiableValueSpliterator<>(split); } @@ -688,32 +577,6 @@ public void forEachRemaining(Consumer> action) { return null; } } - - @Override - public long estimateSize() { - return this.delegate.estimateSize(); - } - - @Override - public long getExactSizeIfKnown() { - return this.delegate.getExactSizeIfKnown(); - } - - @Override - public int characteristics() { - return this.delegate.characteristics(); - } - - @Override - public boolean hasCharacteristics(int characteristics) { - return this.delegate.hasCharacteristics(characteristics); - } - - @Override - public Comparator> getComparator() { - return this.delegate.getComparator(); - } } } - } diff --git a/spring-core/src/main/java/org/springframework/util/xml/StaxEventHandler.java b/spring-core/src/main/java/org/springframework/util/xml/StaxEventHandler.java index d7824aef2b0c..6b76b35496e3 100644 --- a/spring-core/src/main/java/org/springframework/util/xml/StaxEventHandler.java +++ b/spring-core/src/main/java/org/springframework/util/xml/StaxEventHandler.java @@ -28,6 +28,7 @@ import javax.xml.stream.events.Attribute; import javax.xml.stream.events.Namespace; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; import org.xml.sax.Attributes; import org.xml.sax.Locator; @@ -50,6 +51,7 @@ class StaxEventHandler extends AbstractStaxHandler { /** * Construct a new instance of the {@code StaxEventContentHandler} that writes to the * given {@code XMLEventWriter}. A default {@code XMLEventFactory} will be created. + * * @param eventWriter the writer to write events to */ public StaxEventHandler(XMLEventWriter eventWriter) { @@ -60,8 +62,9 @@ public StaxEventHandler(XMLEventWriter eventWriter) { /** * Construct a new instance of the {@code StaxEventContentHandler} that uses the given * event factory to create events and writes to the given {@code XMLEventConsumer}. + * * @param eventWriter the writer to write events to - * @param factory the factory used to create events + * @param factory the factory used to create events */ public StaxEventHandler(XMLEventWriter eventWriter, XMLEventFactory factory) { this.eventFactory = factory; @@ -88,7 +91,7 @@ protected void endDocumentInternal() throws XMLStreamException { @Override protected void startElementInternal(QName name, Attributes atts, - Map namespaceMapping) throws XMLStreamException { + Map namespaceMapping) throws XMLStreamException { List attributes = getAttributes(atts); List namespaces = getNamespaces(namespaceMapping); @@ -157,39 +160,16 @@ protected void commentInternal(String comment) throws XMLStreamException { protected void skippedEntityInternal(String name) { } - - private static final class LocatorLocationAdapter implements Location { - - private final Locator locator; + @Mixin + protected static final class LocatorLocationAdapter extends LocatorLocationAdapterForwarder implements Location { public LocatorLocationAdapter(Locator locator) { - this.locator = locator; - } - - @Override - public int getLineNumber() { - return this.locator.getLineNumber(); - } - - @Override - public int getColumnNumber() { - return this.locator.getColumnNumber(); + super(locator); } @Override public int getCharacterOffset() { return -1; } - - @Override - public String getPublicId() { - return this.locator.getPublicId(); - } - - @Override - public String getSystemId() { - return this.locator.getSystemId(); - } } - } diff --git a/spring-jms/spring-jms.gradle b/spring-jms/spring-jms.gradle index 9014b09663da..932648faadf0 100644 --- a/spring-jms/spring-jms.gradle +++ b/spring-jms/spring-jms.gradle @@ -1,12 +1,15 @@ description = "Spring JMS" dependencies { - api(project(":spring-beans")) + annotationProcessor project(":framework-annotation-processor") + api(project(":spring-beans")) api(project(":spring-core")) api(project(":spring-messaging")) api(project(":spring-tx")) api("io.micrometer:micrometer-observation") compileOnly("jakarta.jms:jakarta.jms-api") + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") optional(project(":spring-aop")) optional(project(":spring-context")) optional(project(":spring-oxm")) diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageConsumer.java b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageConsumer.java index 25eb8a585769..9611f133e48e 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageConsumer.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageConsumer.java @@ -16,10 +16,9 @@ package org.springframework.jms.connection; +import guru.mocker.annotation.mixin.Mixin; import jakarta.jms.JMSException; -import jakarta.jms.Message; import jakarta.jms.MessageConsumer; -import jakarta.jms.MessageListener; import jakarta.jms.Queue; import jakarta.jms.QueueReceiver; import jakarta.jms.Topic; @@ -33,59 +32,26 @@ * @author Juergen Hoeller * @since 2.5.6 */ -class CachedMessageConsumer implements MessageConsumer, QueueReceiver, TopicSubscriber { - - protected final MessageConsumer target; - +@Mixin +class CachedMessageConsumer extends CachedMessageConsumerForwarder implements QueueReceiver, TopicSubscriber { public CachedMessageConsumer(MessageConsumer target) { - this.target = target; - } - - - @Override - public String getMessageSelector() throws JMSException { - return this.target.getMessageSelector(); + super(target); } @Override public @Nullable Queue getQueue() throws JMSException { - return (this.target instanceof QueueReceiver receiver ? receiver.getQueue() : null); + return (target instanceof QueueReceiver receiver ? receiver.getQueue() : null); } @Override public @Nullable Topic getTopic() throws JMSException { - return (this.target instanceof TopicSubscriber subscriber ? subscriber.getTopic() : null); + return (target instanceof TopicSubscriber subscriber ? subscriber.getTopic() : null); } @Override public boolean getNoLocal() throws JMSException { - return (this.target instanceof TopicSubscriber subscriber && subscriber.getNoLocal()); - } - - @Override - public MessageListener getMessageListener() throws JMSException { - return this.target.getMessageListener(); - } - - @Override - public void setMessageListener(MessageListener messageListener) throws JMSException { - this.target.setMessageListener(messageListener); - } - - @Override - public Message receive() throws JMSException { - return this.target.receive(); - } - - @Override - public Message receive(long timeout) throws JMSException { - return this.target.receive(timeout); - } - - @Override - public Message receiveNoWait() throws JMSException { - return this.target.receiveNoWait(); + return (target instanceof TopicSubscriber subscriber && subscriber.getNoLocal()); } @Override @@ -93,10 +59,9 @@ public void close() throws JMSException { // It's a cached MessageConsumer... } - @Override public String toString() { - return "Cached JMS MessageConsumer: " + this.target; + return "Cached JMS MessageConsumer: " + target; } } diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java index 14eb41295af5..55f2b880efb8 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java @@ -16,6 +16,7 @@ package org.springframework.jms.connection; +import guru.mocker.annotation.mixin.Mixin; import jakarta.jms.CompletionListener; import jakarta.jms.Destination; import jakarta.jms.JMSException; @@ -34,9 +35,9 @@ * @author Juergen Hoeller * @since 2.5.3 */ -class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublisher { +@Mixin +class CachedMessageProducer extends CachedMessageProducerForwarder implements QueueSender, TopicPublisher { - private final MessageProducer target; private @Nullable Boolean originalDisableMessageID; @@ -52,7 +53,7 @@ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublis public CachedMessageProducer(MessageProducer target) throws JMSException { - this.target = target; + super(target); this.deliveryMode = target.getDeliveryMode(); this.priority = target.getPriority(); this.timeToLive = target.getTimeToLive(); @@ -62,40 +63,25 @@ public CachedMessageProducer(MessageProducer target) throws JMSException { @Override public void setDisableMessageID(boolean disableMessageID) throws JMSException { if (this.originalDisableMessageID == null) { - this.originalDisableMessageID = this.target.getDisableMessageID(); + this.originalDisableMessageID = super.getDisableMessageID(); } - this.target.setDisableMessageID(disableMessageID); - } - - @Override - public boolean getDisableMessageID() throws JMSException { - return this.target.getDisableMessageID(); + super.setDisableMessageID(disableMessageID); } @Override public void setDisableMessageTimestamp(boolean disableMessageTimestamp) throws JMSException { if (this.originalDisableMessageTimestamp == null) { - this.originalDisableMessageTimestamp = this.target.getDisableMessageTimestamp(); + this.originalDisableMessageTimestamp = super.getDisableMessageTimestamp(); } - this.target.setDisableMessageTimestamp(disableMessageTimestamp); - } - - @Override - public boolean getDisableMessageTimestamp() throws JMSException { - return this.target.getDisableMessageTimestamp(); + super.setDisableMessageTimestamp(disableMessageTimestamp); } @Override public void setDeliveryDelay(long deliveryDelay) throws JMSException { if (this.originalDeliveryDelay == null) { - this.originalDeliveryDelay = this.target.getDeliveryDelay(); + this.originalDeliveryDelay = super.getDeliveryDelay(); } - this.target.setDeliveryDelay(deliveryDelay); - } - - @Override - public long getDeliveryDelay() throws JMSException { - return this.target.getDeliveryDelay(); + super.setDeliveryDelay(deliveryDelay); } @Override @@ -128,116 +114,81 @@ public long getTimeToLive() { return this.timeToLive; } - @Override - public Destination getDestination() throws JMSException { - return this.target.getDestination(); - } - @Override public Queue getQueue() throws JMSException { - return (Queue) this.target.getDestination(); + return (Queue) super.getDestination(); } @Override public Topic getTopic() throws JMSException { - return (Topic) this.target.getDestination(); + return (Topic) super.getDestination(); } @Override public void send(Message message) throws JMSException { - this.target.send(message, this.deliveryMode, this.priority, this.timeToLive); - } - - @Override - public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { - this.target.send(message, deliveryMode, priority, timeToLive); + super.send(message, this.deliveryMode, this.priority, this.timeToLive); } @Override public void send(Destination destination, Message message) throws JMSException { - this.target.send(destination, message, this.deliveryMode, this.priority, this.timeToLive); - } - - @Override - public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { - this.target.send(destination, message, deliveryMode, priority, timeToLive); + super.send(destination, message, this.deliveryMode, this.priority, this.timeToLive); } @Override public void send(Message message, CompletionListener completionListener) throws JMSException { - this.target.send(message, this.deliveryMode, this.priority, this.timeToLive, completionListener); - } - - @Override - public void send(Message message, int deliveryMode, int priority, long timeToLive, - CompletionListener completionListener) throws JMSException { - - this.target.send(message, deliveryMode, priority, timeToLive, completionListener); + super.send(message, this.deliveryMode, this.priority, this.timeToLive, completionListener); } @Override public void send(Destination destination, Message message, CompletionListener completionListener) throws JMSException { - this.target.send(destination, message, this.deliveryMode, this.priority, this.timeToLive, completionListener); - } - - @Override - public void send(Destination destination, Message message, int deliveryMode, int priority, - long timeToLive, CompletionListener completionListener) throws JMSException { - - this.target.send(destination, message, deliveryMode, priority, timeToLive, completionListener); - + super.send(destination, message, this.deliveryMode, this.priority, this.timeToLive, completionListener); } @Override public void send(Queue queue, Message message) throws JMSException { - this.target.send(queue, message, this.deliveryMode, this.priority, this.timeToLive); - } - - @Override - public void send(Queue queue, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { - this.target.send(queue, message, deliveryMode, priority, timeToLive); + super.send(queue, message, this.deliveryMode, this.priority, this.timeToLive); } @Override public void publish(Message message) throws JMSException { - this.target.send(message, this.deliveryMode, this.priority, this.timeToLive); + super.send(message, this.deliveryMode, this.priority, this.timeToLive); } @Override public void publish(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { - this.target.send(message, deliveryMode, priority, timeToLive); + super.send(message, deliveryMode, priority, timeToLive); } @Override public void publish(Topic topic, Message message) throws JMSException { - this.target.send(topic, message, this.deliveryMode, this.priority, this.timeToLive); + super.send(topic, message, this.deliveryMode, this.priority, this.timeToLive); } @Override public void publish(Topic topic, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { - this.target.send(topic, message, deliveryMode, priority, timeToLive); + super.send(topic, message, deliveryMode, priority, timeToLive); } @Override public void close() throws JMSException { // It's a cached MessageProducer... reset properties only. if (this.originalDisableMessageID != null) { - this.target.setDisableMessageID(this.originalDisableMessageID); + super.setDisableMessageID(this.originalDisableMessageID); this.originalDisableMessageID = null; } if (this.originalDisableMessageTimestamp != null) { - this.target.setDisableMessageTimestamp(this.originalDisableMessageTimestamp); + super.setDisableMessageTimestamp(this.originalDisableMessageTimestamp); this.originalDisableMessageTimestamp = null; } if (this.originalDeliveryDelay != null) { - this.target.setDeliveryDelay(this.originalDeliveryDelay); + super.setDeliveryDelay(this.originalDeliveryDelay); this.originalDeliveryDelay = null; } } @Override public String toString() { - return "Cached JMS MessageProducer: " + this.target; + return "Cached JMS MessageProducer: " + target; } } diff --git a/spring-r2dbc/spring-r2dbc.gradle b/spring-r2dbc/spring-r2dbc.gradle index ccb9329cc7b5..e08e5d4483dc 100644 --- a/spring-r2dbc/spring-r2dbc.gradle +++ b/spring-r2dbc/spring-r2dbc.gradle @@ -3,13 +3,16 @@ description = "Spring R2DBC" apply plugin: "kotlin" dependencies { - api(project(":spring-beans")) + annotationProcessor project(":framework-annotation-processor") + api(project(":spring-beans")) api(project(":spring-core")) api(project(":spring-tx")) api("io.projectreactor:reactor-core") api("io.r2dbc:r2dbc-spi") compileOnly("com.google.code.findbugs:jsr305") // for r2dbc-spi - optional("org.jetbrains.kotlin:kotlin-reflect") + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DefaultDatabaseClient.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DefaultDatabaseClient.java index ee957d4c3f84..3c9ede5e2193 100644 --- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DefaultDatabaseClient.java +++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DefaultDatabaseClient.java @@ -32,6 +32,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import guru.mocker.annotation.mixin.Mixin; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.Parameter; @@ -576,34 +577,10 @@ Mono close() { } } - - static class StatementWrapper implements BindTarget { - - final Statement statement; - + @Mixin + static class StatementWrapper extends StatementWrapperForwarder implements BindTarget { StatementWrapper(Statement statement) { - this.statement = statement; - } - - @Override - public void bind(String identifier, Object value) { - this.statement.bind(identifier, value); - } - - @Override - public void bind(int index, Object value) { - this.statement.bind(index, value); - } - - @Override - public void bindNull(String identifier, Class type) { - this.statement.bindNull(identifier, type); - } - - @Override - public void bindNull(int index, Class type) { - this.statement.bindNull(index, type); + super(statement); } } - } diff --git a/spring-test/spring-test.gradle b/spring-test/spring-test.gradle index 58284a65fd37..324ec4a79e37 100644 --- a/spring-test/spring-test.gradle +++ b/spring-test/spring-test.gradle @@ -4,6 +4,9 @@ apply plugin: "kotlin" apply plugin: "kotlinx-serialization" dependencies { + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + annotationProcessor(project(":framework-annotation-processor")) api(project(":spring-core")) compileOnly("com.google.code.findbugs:jsr305") // for Reactor optional(project(":spring-aop")) diff --git a/spring-test/src/main/java/org/springframework/mock/web/server/MockWebSession.java b/spring-test/src/main/java/org/springframework/mock/web/server/MockWebSession.java index a23b17f88dfc..9b131c855bee 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/server/MockWebSession.java +++ b/spring-test/src/main/java/org/springframework/mock/web/server/MockWebSession.java @@ -17,12 +17,9 @@ package org.springframework.mock.web.server; import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; -import reactor.core.publisher.Mono; import org.springframework.util.Assert; import org.springframework.web.server.WebSession; @@ -40,84 +37,29 @@ * @author Rossen Stoyanchev * @since 5.1 */ -public class MockWebSession implements WebSession { - - private final WebSession delegate; - +public class MockWebSession extends MockWebSessionForwarder implements WebSession { public MockWebSession() { - this(null); + this((Clock) null); + } + + @Mixin + MockWebSession(WebSession delegate) { + super(delegate); } public MockWebSession(@Nullable Clock clock) { + this(createSession(clock)); + } + + private static WebSession createSession(@Nullable Clock clock) { InMemoryWebSessionStore sessionStore = new InMemoryWebSessionStore(); if (clock != null) { sessionStore.setClock(clock); } WebSession session = sessionStore.createWebSession().block(); Assert.state(session != null, "WebSession must not be null"); - this.delegate = session; - } - - - @Override - public String getId() { - return this.delegate.getId(); - } - - @Override - public Map getAttributes() { - return this.delegate.getAttributes(); - } - - @Override - public void start() { - this.delegate.start(); - } - - @Override - public boolean isStarted() { - return this.delegate.isStarted(); - } - - @Override - public Mono changeSessionId() { - return this.delegate.changeSessionId(); - } - - @Override - public Mono invalidate() { - return this.delegate.invalidate(); - } - - @Override - public Mono save() { - return this.delegate.save(); - } - - @Override - public boolean isExpired() { - return this.delegate.isExpired(); - } - - @Override - public Instant getCreationTime() { - return this.delegate.getCreationTime(); - } - - @Override - public Instant getLastAccessTime() { - return this.delegate.getLastAccessTime(); - } - - @Override - public void setMaxIdleTime(Duration maxIdleTime) { - this.delegate.setMaxIdleTime(maxIdleTime); - } - - @Override - public Duration getMaxIdleTime() { - return this.delegate.getMaxIdleTime(); + return session; } } diff --git a/spring-web/spring-web.gradle b/spring-web/spring-web.gradle index df797daae639..8699faff4a6d 100644 --- a/spring-web/spring-web.gradle +++ b/spring-web/spring-web.gradle @@ -4,11 +4,17 @@ apply plugin: "kotlin" apply plugin: "kotlinx-serialization" dependencies { + annotationProcessor project(":framework-annotation-processor") api(project(":spring-beans")) api(project(":spring-core")) api("io.micrometer:micrometer-observation") compileOnly("io.projectreactor.tools:blockhound") compileOnly("com.google.code.findbugs:jsr305") // for Reactor + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + testFixturesCompileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + testFixturesAnnotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + testFixturesAnnotationProcessor(project(":framework-annotation-processor")) optional(project(":spring-aop")) optional(project(":spring-context")) optional(project(":spring-oxm")) diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequestDecorator.java b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequestDecorator.java index 8cd986fa7369..f25873899570 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequestDecorator.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequestDecorator.java @@ -16,20 +16,9 @@ package org.springframework.http.client.reactive; -import java.net.URI; -import java.util.Map; -import java.util.function.Supplier; +import guru.mocker.annotation.mixin.Mixin; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Mono; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.http.HttpCookie; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; import org.springframework.util.Assert; -import org.springframework.util.MultiValueMap; /** * Wraps another {@link ClientHttpRequest} and delegates all methods to it. @@ -38,82 +27,16 @@ * @author Rossen Stoyanchev * @since 5.0 */ -public class ClientHttpRequestDecorator implements ClientHttpRequest { - - private final ClientHttpRequest delegate; - +public class ClientHttpRequestDecorator extends ClientHttpRequestDecoratorForwarder implements ClientHttpRequest { + @Mixin public ClientHttpRequestDecorator(ClientHttpRequest delegate) { + super(delegate); Assert.notNull(delegate, "Delegate is required"); - this.delegate = delegate; } - public ClientHttpRequest getDelegate() { - return this.delegate; - } - - - // ClientHttpRequest delegation methods... - - @Override - public HttpMethod getMethod() { - return this.delegate.getMethod(); - } - - @Override - public URI getURI() { - return this.delegate.getURI(); - } - - @Override - public HttpHeaders getHeaders() { - return this.delegate.getHeaders(); - } - - @Override - public MultiValueMap getCookies() { - return this.delegate.getCookies(); - } - - @Override - public Map getAttributes() { - return this.delegate.getAttributes(); - } - - @Override - public DataBufferFactory bufferFactory() { - return this.delegate.bufferFactory(); - } - - @Override - public T getNativeRequest() { - return this.delegate.getNativeRequest(); - } - - @Override - public void beforeCommit(Supplier> action) { - this.delegate.beforeCommit(action); - } - - @Override - public boolean isCommitted() { - return this.delegate.isCommitted(); - } - - @Override - public Mono writeWith(Publisher body) { - return this.delegate.writeWith(body); - } - - @Override - public Mono writeAndFlushWith(Publisher> body) { - return this.delegate.writeAndFlushWith(body); - } - - @Override - public Mono setComplete() { - return this.delegate.setComplete(); + return delegate; } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java index e5659c0eae16..5c9e3e1ddb10 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java @@ -16,14 +16,9 @@ package org.springframework.http.client.reactive; -import reactor.core.publisher.Flux; +import guru.mocker.annotation.mixin.Mixin; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.ResponseCookie; import org.springframework.util.Assert; -import org.springframework.util.MultiValueMap; /** * Wraps another {@link ClientHttpResponse} and delegates all methods to it. @@ -32,47 +27,16 @@ * @author Rossen Stoyanchev * @since 5.0 */ -public class ClientHttpResponseDecorator implements ClientHttpResponse { - - private final ClientHttpResponse delegate; - +public class ClientHttpResponseDecorator extends ClientHttpResponseDecoratorForwarder implements ClientHttpResponse { + @Mixin public ClientHttpResponseDecorator(ClientHttpResponse delegate) { + super(delegate); Assert.notNull(delegate, "Delegate is required"); - this.delegate = delegate; } - public ClientHttpResponse getDelegate() { - return this.delegate; - } - - - // ClientHttpResponse delegation methods... - - @Override - public String getId() { - return this.delegate.getId(); - } - - @Override - public HttpStatusCode getStatusCode() { - return this.delegate.getStatusCode(); - } - - @Override - public HttpHeaders getHeaders() { - return this.delegate.getHeaders(); - } - - @Override - public MultiValueMap getCookies() { - return this.delegate.getCookies(); - } - - @Override - public Flux getBody() { - return this.delegate.getBody(); + return delegate; } @Override diff --git a/spring-web/src/main/java/org/springframework/http/client/support/HttpRequestWrapper.java b/spring-web/src/main/java/org/springframework/http/client/support/HttpRequestWrapper.java index e48e84cf285a..d70528275d1b 100644 --- a/spring-web/src/main/java/org/springframework/http/client/support/HttpRequestWrapper.java +++ b/spring-web/src/main/java/org/springframework/http/client/support/HttpRequestWrapper.java @@ -16,11 +16,8 @@ package org.springframework.http.client.support; -import java.net.URI; -import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import org.springframework.util.Assert; @@ -33,58 +30,23 @@ * @author Arjen Poutsma * @since 3.1 */ -public class HttpRequestWrapper implements HttpRequest { - - private final HttpRequest request; - +public class HttpRequestWrapper extends HttpRequestWrapperForwarder implements HttpRequest { /** * Create a new {@code HttpRequest} wrapping the given request object. * @param request the request object to be wrapped */ + @Mixin public HttpRequestWrapper(HttpRequest request) { + super(request); Assert.notNull(request, "HttpRequest must not be null"); - this.request = request; } - /** * Return the wrapped request. */ public HttpRequest getRequest() { - return this.request; - } - - /** - * Return the method of the wrapped request. - */ - @Override - public HttpMethod getMethod() { - return this.request.getMethod(); - } - - /** - * Return the URI of the wrapped request. - */ - @Override - public URI getURI() { - return this.request.getURI(); - } - - /** - * Return the attributes of the wrapped request. - */ - @Override - public Map getAttributes() { - return this.request.getAttributes(); - } - - /** - * Return the headers of the wrapped request. - */ - @Override - public HttpHeaders getHeaders() { - return this.request.getHeaders(); + return request; } } diff --git a/spring-web/src/main/java/org/springframework/web/bind/EscapedErrors.java b/spring-web/src/main/java/org/springframework/web/bind/EscapedErrors.java index 65723509dc35..e7628c6845db 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/EscapedErrors.java +++ b/spring-web/src/main/java/org/springframework/web/bind/EscapedErrors.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; @@ -41,173 +42,54 @@ * @see org.springframework.web.servlet.support.RequestContext#getErrors * @see org.springframework.web.servlet.tags.BindTag */ -public class EscapedErrors implements Errors { - - private final Errors source; - +public class EscapedErrors extends EscapedErrorsForwarder implements Errors { /** * Create a new EscapedErrors instance for the given source instance. */ + @Mixin public EscapedErrors(Errors source) { + super(source); Assert.notNull(source, "Errors source must not be null"); - this.source = source; } public Errors getSource() { - return this.source; - } - - - @Override - public String getObjectName() { - return this.source.getObjectName(); - } - - @Override - public void setNestedPath(String nestedPath) { - this.source.setNestedPath(nestedPath); - } - - @Override - public String getNestedPath() { - return this.source.getNestedPath(); - } - - @Override - public void pushNestedPath(String subPath) { - this.source.pushNestedPath(subPath); - } - - @Override - public void popNestedPath() throws IllegalStateException { - this.source.popNestedPath(); - } - - - @Override - public void reject(String errorCode) { - this.source.reject(errorCode); - } - - @Override - public void reject(String errorCode, String defaultMessage) { - this.source.reject(errorCode, defaultMessage); - } - - @Override - public void reject(String errorCode, Object @Nullable [] errorArgs, @Nullable String defaultMessage) { - this.source.reject(errorCode, errorArgs, defaultMessage); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode) { - this.source.rejectValue(field, errorCode); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode, String defaultMessage) { - this.source.rejectValue(field, errorCode, defaultMessage); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode, - Object @Nullable [] errorArgs, @Nullable String defaultMessage) { - - this.source.rejectValue(field, errorCode, errorArgs, defaultMessage); - } - - @Override - public void addAllErrors(Errors errors) { - this.source.addAllErrors(errors); - } - - - @Override - public boolean hasErrors() { - return this.source.hasErrors(); - } - - @Override - public int getErrorCount() { - return this.source.getErrorCount(); + return source; } @Override public List getAllErrors() { - return escapeObjectErrors(this.source.getAllErrors()); + return escapeObjectErrors(source.getAllErrors()); } - @Override - public boolean hasGlobalErrors() { - return this.source.hasGlobalErrors(); - } - - @Override - public int getGlobalErrorCount() { - return this.source.getGlobalErrorCount(); - } @Override public List getGlobalErrors() { - return escapeObjectErrors(this.source.getGlobalErrors()); + return escapeObjectErrors(source.getGlobalErrors()); } @Override public @Nullable ObjectError getGlobalError() { - return escapeObjectError(this.source.getGlobalError()); - } - - @Override - public boolean hasFieldErrors() { - return this.source.hasFieldErrors(); - } - - @Override - public int getFieldErrorCount() { - return this.source.getFieldErrorCount(); - } - - @Override - public List getFieldErrors() { - return this.source.getFieldErrors(); - } - - @Override - public @Nullable FieldError getFieldError() { - return this.source.getFieldError(); + return escapeObjectError(source.getGlobalError()); } - @Override - public boolean hasFieldErrors(String field) { - return this.source.hasFieldErrors(field); - } - - @Override - public int getFieldErrorCount(String field) { - return this.source.getFieldErrorCount(field); - } @Override public List getFieldErrors(String field) { - return escapeObjectErrors(this.source.getFieldErrors(field)); + return escapeObjectErrors(source.getFieldErrors(field)); } @Override public @Nullable FieldError getFieldError(String field) { - return escapeObjectError(this.source.getFieldError(field)); + return escapeObjectError(source.getFieldError(field)); } @Override public @Nullable Object getFieldValue(String field) { - Object value = this.source.getFieldValue(field); + Object value = source.getFieldValue(field); return (value instanceof String text ? HtmlUtils.htmlEscape(text) : value); } - @Override - public @Nullable Class getFieldType(String field) { - return this.source.getFieldType(field); - } @SuppressWarnings("unchecked") private @Nullable T escapeObjectError(@Nullable T source) { diff --git a/spring-web/src/main/java/org/springframework/web/bind/support/WebExchangeBindException.java b/spring-web/src/main/java/org/springframework/web/bind/support/WebExchangeBindException.java index 6ec168b3e105..f262031e8d53 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/support/WebExchangeBindException.java +++ b/spring-web/src/main/java/org/springframework/web/bind/support/WebExchangeBindException.java @@ -16,21 +16,16 @@ package org.springframework.web.bind.support; -import java.beans.PropertyEditor; -import java.util.List; import java.util.Locale; -import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; -import org.springframework.beans.PropertyEditorRegistry; import org.springframework.context.MessageSource; import org.springframework.core.MethodParameter; import org.springframework.util.Assert; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.BindingResult; -import org.springframework.validation.Errors; -import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.util.BindErrorUtils; @@ -43,13 +38,18 @@ * @since 5.0 */ @SuppressWarnings("serial") -public class WebExchangeBindException extends ServerWebInputException implements BindingResult { - - private final BindingResult bindingResult; +public class WebExchangeBindException extends WebExchangeBindExceptionForwarder implements BindingResult { + final BindingResult bindingResult; public WebExchangeBindException(MethodParameter parameter, BindingResult bindingResult) { - super("Validation failure", parameter, null, null, null); + this("Validation failure", parameter, null, null, null, bindingResult); + } + + @Mixin(grandparent = ServerWebInputException.class) + private WebExchangeBindException(String reason, @Nullable MethodParameter parameter, @Nullable Throwable cause, + @Nullable String messageDetailCode, Object @Nullable [] messageDetailArguments, BindingResult bindingResult) { + super(reason, parameter, cause, messageDetailCode, messageDetailArguments, bindingResult); this.bindingResult = bindingResult; getBody().setDetail("Invalid request content."); } @@ -79,213 +79,6 @@ public Object[] getDetailMessageArguments(MessageSource source, Locale locale) { BindErrorUtils.resolveAndJoin(getFieldErrors(), source, locale)}; } - - // BindingResult implementation methods - - @Override - public String getObjectName() { - return this.bindingResult.getObjectName(); - } - - @Override - public void setNestedPath(String nestedPath) { - this.bindingResult.setNestedPath(nestedPath); - } - - @Override - public String getNestedPath() { - return this.bindingResult.getNestedPath(); - } - - @Override - public void pushNestedPath(String subPath) { - this.bindingResult.pushNestedPath(subPath); - } - - @Override - public void popNestedPath() throws IllegalStateException { - this.bindingResult.popNestedPath(); - } - - @Override - public void reject(String errorCode) { - this.bindingResult.reject(errorCode); - } - - @Override - public void reject(String errorCode, String defaultMessage) { - this.bindingResult.reject(errorCode, defaultMessage); - } - - @Override - public void reject(String errorCode, Object @Nullable [] errorArgs, @Nullable String defaultMessage) { - this.bindingResult.reject(errorCode, errorArgs, defaultMessage); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode) { - this.bindingResult.rejectValue(field, errorCode); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode, String defaultMessage) { - this.bindingResult.rejectValue(field, errorCode, defaultMessage); - } - - @Override - public void rejectValue(@Nullable String field, String errorCode, - Object @Nullable [] errorArgs, @Nullable String defaultMessage) { - - this.bindingResult.rejectValue(field, errorCode, errorArgs, defaultMessage); - } - - @Override - public void addAllErrors(Errors errors) { - this.bindingResult.addAllErrors(errors); - } - - @Override - public boolean hasErrors() { - return this.bindingResult.hasErrors(); - } - - @Override - public int getErrorCount() { - return this.bindingResult.getErrorCount(); - } - - @Override - public List getAllErrors() { - return this.bindingResult.getAllErrors(); - } - - @Override - public boolean hasGlobalErrors() { - return this.bindingResult.hasGlobalErrors(); - } - - @Override - public int getGlobalErrorCount() { - return this.bindingResult.getGlobalErrorCount(); - } - - @Override - public List getGlobalErrors() { - return this.bindingResult.getGlobalErrors(); - } - - @Override - public @Nullable ObjectError getGlobalError() { - return this.bindingResult.getGlobalError(); - } - - @Override - public boolean hasFieldErrors() { - return this.bindingResult.hasFieldErrors(); - } - - @Override - public int getFieldErrorCount() { - return this.bindingResult.getFieldErrorCount(); - } - - @Override - public List getFieldErrors() { - return this.bindingResult.getFieldErrors(); - } - - @Override - public @Nullable FieldError getFieldError() { - return this.bindingResult.getFieldError(); - } - - @Override - public boolean hasFieldErrors(String field) { - return this.bindingResult.hasFieldErrors(field); - } - - @Override - public int getFieldErrorCount(String field) { - return this.bindingResult.getFieldErrorCount(field); - } - - @Override - public List getFieldErrors(String field) { - return this.bindingResult.getFieldErrors(field); - } - - @Override - public @Nullable FieldError getFieldError(String field) { - return this.bindingResult.getFieldError(field); - } - - @Override - public @Nullable Object getFieldValue(String field) { - return this.bindingResult.getFieldValue(field); - } - - @Override - public @Nullable Class getFieldType(String field) { - return this.bindingResult.getFieldType(field); - } - - @Override - public @Nullable Object getTarget() { - return this.bindingResult.getTarget(); - } - - @Override - public Map getModel() { - return this.bindingResult.getModel(); - } - - @Override - public @Nullable Object getRawFieldValue(String field) { - return this.bindingResult.getRawFieldValue(field); - } - - @Override - @SuppressWarnings("rawtypes") - public @Nullable PropertyEditor findEditor(@Nullable String field, @Nullable Class valueType) { - return this.bindingResult.findEditor(field, valueType); - } - - @Override - public @Nullable PropertyEditorRegistry getPropertyEditorRegistry() { - return this.bindingResult.getPropertyEditorRegistry(); - } - - @Override - public String[] resolveMessageCodes(String errorCode) { - return this.bindingResult.resolveMessageCodes(errorCode); - } - - @Override - public String[] resolveMessageCodes(String errorCode, String field) { - return this.bindingResult.resolveMessageCodes(errorCode, field); - } - - @Override - public void addError(ObjectError error) { - this.bindingResult.addError(error); - } - - @Override - public void recordFieldValue(String field, Class type, @Nullable Object value) { - this.bindingResult.recordFieldValue(field, type, value); - } - - @Override - public void recordSuppressedField(String field) { - this.bindingResult.recordSuppressedField(field); - } - - @Override - public String[] getSuppressedFields() { - return this.bindingResult.getSuppressedFields(); - } - - /** * Returns diagnostic information about the errors held in this object. */ diff --git a/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java index 8ec21be4ea48..79c30af9c1b2 100644 --- a/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java +++ b/spring-web/src/main/java/org/springframework/web/client/ClientHttpResponseDecorator.java @@ -16,11 +16,8 @@ package org.springframework.web.client; -import java.io.IOException; -import java.io.InputStream; +import guru.mocker.annotation.mixin.Mixin; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpResponse; import org.springframework.util.Assert; @@ -31,48 +28,19 @@ * @author Rossen Stoyanchev * @since 6.0 */ -class ClientHttpResponseDecorator implements ClientHttpResponse { - - private final ClientHttpResponse delegate; - +class ClientHttpResponseDecorator extends ClientHttpResponseDecoratorForwarder implements ClientHttpResponse { + @Mixin public ClientHttpResponseDecorator(ClientHttpResponse delegate) { + super(delegate); Assert.notNull(delegate, "ClientHttpResponse delegate is required"); - this.delegate = delegate; } - /** * Return the wrapped response. */ public ClientHttpResponse getDelegate() { - return this.delegate; - } - - - @Override - public HttpStatusCode getStatusCode() throws IOException { - return this.delegate.getStatusCode(); - } - - @Override - public String getStatusText() throws IOException { - return this.delegate.getStatusText(); - } - - @Override - public HttpHeaders getHeaders() { - return this.delegate.getHeaders(); - } - - @Override - public InputStream getBody() throws IOException { - return this.delegate.getBody(); - } - - @Override - public void close() { - this.delegate.close(); + return delegate; } } diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpExchangeAdapterDecorator.java b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpExchangeAdapterDecorator.java index 87a92b20fafa..c0bc9c9edb15 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpExchangeAdapterDecorator.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpExchangeAdapterDecorator.java @@ -16,11 +16,7 @@ package org.springframework.web.service.invoker; -import org.jspecify.annotations.Nullable; - -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; +import guru.mocker.annotation.mixin.Mixin; /** * {@link HttpExchangeAdapter} that wraps and delegates to another adapter instance. @@ -28,52 +24,18 @@ * @author Rossen Stoyanchev * @since 7.0 */ -public class HttpExchangeAdapterDecorator implements HttpExchangeAdapter { - - private final HttpExchangeAdapter delegate; - +public class HttpExchangeAdapterDecorator extends HttpExchangeAdapterDecoratorForwarder implements HttpExchangeAdapter { + @Mixin public HttpExchangeAdapterDecorator(HttpExchangeAdapter delegate) { - this.delegate = delegate; + super(delegate); } - /** * Return the wrapped delegate {@code HttpExchangeAdapter}. */ public HttpExchangeAdapter getHttpExchangeAdapter() { - return this.delegate; - } - - - @Override - public boolean supportsRequestAttributes() { - return this.delegate.supportsRequestAttributes(); - } - - @Override - public void exchange(HttpRequestValues requestValues) { - this.delegate.exchange(requestValues); - } - - @Override - public HttpHeaders exchangeForHeaders(HttpRequestValues requestValues) { - return this.delegate.exchangeForHeaders(requestValues); - } - - @Override - public @Nullable T exchangeForBody(HttpRequestValues requestValues, ParameterizedTypeReference bodyType) { - return this.delegate.exchangeForBody(requestValues, bodyType); - } - - @Override - public ResponseEntity exchangeForBodilessEntity(HttpRequestValues requestValues) { - return this.delegate.exchangeForBodilessEntity(requestValues); - } - - @Override - public ResponseEntity exchangeForEntity(HttpRequestValues requestValues, ParameterizedTypeReference bodyType) { - return this.delegate.exchangeForEntity(requestValues, bodyType); + return delegate; } } diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponents.java b/spring-web/src/main/java/org/springframework/web/util/UriComponents.java index 732f26a79cf7..50fbdb91eb58 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponents.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponents.java @@ -348,7 +348,7 @@ private static class VarArgsTemplateVariables implements UriTemplateVariables { private final Iterator<@Nullable Object> valueIterator; public VarArgsTemplateVariables(@Nullable Object... uriVariableValues) { - this.valueIterator = Arrays.asList(uriVariableValues).iterator(); + this.valueIterator = Arrays.<@Nullable Object>asList(uriVariableValues).iterator(); } @Override diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/server/MockWebSession.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/server/MockWebSession.java index 2d1657e69692..bb3926ad3d24 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/server/MockWebSession.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/server/MockWebSession.java @@ -17,12 +17,9 @@ package org.springframework.web.testfixture.server; import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; -import reactor.core.publisher.Mono; import org.springframework.util.Assert; import org.springframework.web.server.WebSession; @@ -40,84 +37,29 @@ * @author Rossen Stoyanchev * @since 5.1 */ -public class MockWebSession implements WebSession { - - private final WebSession delegate; - +public class MockWebSession extends MockWebSessionForwarder implements WebSession { public MockWebSession() { - this(null); + this((Clock) null); + } + + @Mixin + MockWebSession(WebSession delegate) { + super(delegate); } public MockWebSession(@Nullable Clock clock) { + this(createSession(clock)); + } + + private static WebSession createSession(@Nullable Clock clock) { InMemoryWebSessionStore sessionStore = new InMemoryWebSessionStore(); if (clock != null) { sessionStore.setClock(clock); } WebSession session = sessionStore.createWebSession().block(); Assert.state(session != null, "WebSession must not be null"); - this.delegate = session; - } - - - @Override - public String getId() { - return this.delegate.getId(); - } - - @Override - public Map getAttributes() { - return this.delegate.getAttributes(); - } - - @Override - public void start() { - this.delegate.start(); - } - - @Override - public boolean isStarted() { - return this.delegate.isStarted(); - } - - @Override - public Mono changeSessionId() { - return this.delegate.changeSessionId(); - } - - @Override - public Mono invalidate() { - return this.delegate.invalidate(); - } - - @Override - public Mono save() { - return this.delegate.save(); - } - - @Override - public boolean isExpired() { - return this.delegate.isExpired(); - } - - @Override - public Instant getCreationTime() { - return this.delegate.getCreationTime(); - } - - @Override - public Instant getLastAccessTime() { - return this.delegate.getLastAccessTime(); - } - - @Override - public void setMaxIdleTime(Duration maxIdleTime) { - this.delegate.setMaxIdleTime(maxIdleTime); - } - - @Override - public Duration getMaxIdleTime() { - return this.delegate.getMaxIdleTime(); + return session; } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java index 769cd520653f..7bf2428602d6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/DelegatingWebFluxConfiguration.java @@ -18,19 +18,12 @@ import java.util.List; -import org.jspecify.annotations.Nullable; +import guru.mocker.annotation.mixin.Mixin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.format.FormatterRegistry; -import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.CollectionUtils; -import org.springframework.validation.MessageCodesResolver; -import org.springframework.validation.Validator; import org.springframework.web.ErrorResponse; -import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; -import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer; -import org.springframework.web.reactive.socket.server.WebSocketService; /** * A subclass of {@code WebFluxConfigurationSupport} that detects and delegates @@ -42,91 +35,28 @@ * @since 5.0 */ @Configuration(proxyBeanMethods = false) -public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport { +public class DelegatingWebFluxConfiguration extends DelegatingWebFluxConfigurationForwarder { - private final WebFluxConfigurerComposite configurers = new WebFluxConfigurerComposite(); + public DelegatingWebFluxConfiguration() { + this(new WebFluxConfigurerComposite()); + } + @Mixin(grandparent = WebFluxConfigurationSupport.class) + public DelegatingWebFluxConfiguration(WebFluxConfigurerComposite webFluxConfigurerComposite) { + super(webFluxConfigurerComposite); + } @Autowired(required = false) public void setConfigurers(List configurers) { if (!CollectionUtils.isEmpty(configurers)) { - this.configurers.addWebFluxConfigurers(configurers); + webFluxConfigurerComposite.addWebFluxConfigurers(configurers); } } - - @Override - protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { - this.configurers.configureHttpMessageCodecs(configurer); - } - - @Override - protected void addFormatters(FormatterRegistry registry) { - this.configurers.addFormatters(registry); - } - - @Override - protected @Nullable Validator getValidator() { - Validator validator = this.configurers.getValidator(); - return (validator != null ? validator : super.getValidator()); - } - - @Override - protected @Nullable MessageCodesResolver getMessageCodesResolver() { - MessageCodesResolver messageCodesResolver = this.configurers.getMessageCodesResolver(); - return (messageCodesResolver != null ? messageCodesResolver : super.getMessageCodesResolver()); - } - - @Override - protected void addCorsMappings(CorsRegistry registry) { - this.configurers.addCorsMappings(registry); - } - - @Override - protected void configureBlockingExecution(BlockingExecutionConfigurer configurer) { - this.configurers.configureBlockingExecution(configurer); - } - @Override - protected void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { - this.configurers.configureContentTypeResolver(builder); + public void configureErrorResponseInterceptors(List interceptors) { + webFluxConfigurerComposite.addErrorResponseInterceptors(interceptors); } - @Override - protected void configureApiVersioning(ApiVersionConfigurer configurer) { - this.configurers.configureApiVersioning(configurer); - } - - @Override - public void configurePathMatching(PathMatchConfigurer configurer) { - this.configurers.configurePathMatching(configurer); - } - - @Override - protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { - this.configurers.configureArgumentResolvers(configurer); - } - - @Override - protected void configureErrorResponseInterceptors(List interceptors) { - this.configurers.addErrorResponseInterceptors(interceptors); - } - - - @Override - protected void addResourceHandlers(ResourceHandlerRegistry registry) { - this.configurers.addResourceHandlers(registry); - } - - @Override - protected void configureViewResolvers(ViewResolverRegistry registry) { - this.configurers.configureViewResolvers(registry); - } - - @Override - protected @Nullable WebSocketService getWebSocketService() { - WebSocketService service = this.configurers.getWebSocketService(); - return (service != null ? service : super.getWebSocketService()); - } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java index f62eb8e0951e..657fc2e23852 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java @@ -16,27 +16,9 @@ package org.springframework.web.reactive.function.client.support; -import java.util.List; -import java.util.Optional; -import java.util.OptionalLong; +import guru.mocker.annotation.mixin.Mixin; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseCookie; -import org.springframework.http.ResponseEntity; -import org.springframework.http.client.reactive.ClientHttpResponse; -import org.springframework.util.Assert; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.ExchangeStrategies; -import org.springframework.web.reactive.function.client.WebClientResponseException; /** * Implementation of the {@link ClientResponse} interface that can be subclassed @@ -47,21 +29,17 @@ * @author Arjen Poutsma * @since 5.0.5 */ -public class ClientResponseWrapper implements ClientResponse { - - private final ClientResponse delegate; - +@Mixin +public class ClientResponseWrapper extends ClientResponseWrapperForwarder implements ClientResponse { /** * Create a new {@code ClientResponseWrapper} that wraps the given response. * @param delegate the response to wrap */ public ClientResponseWrapper(ClientResponse delegate) { - Assert.notNull(delegate, "Delegate is required"); - this.delegate = delegate; + super(delegate); } - /** * Return the wrapped request. */ @@ -69,140 +47,22 @@ public ClientResponse response() { return this.delegate; } - @Override - public HttpStatusCode statusCode() { - return this.delegate.statusCode(); - } - - @Override - public Headers headers() { - return this.delegate.headers(); - } - - @Override - public MultiValueMap cookies() { - return this.delegate.cookies(); - } - - @Override - public ExchangeStrategies strategies() { - return this.delegate.strategies(); - } - - @Override - public HttpRequest request() { - return this.delegate.request(); - } - - @Override - public T body(BodyExtractor extractor) { - return this.delegate.body(extractor); - } - - @Override - public Mono bodyToMono(Class elementClass) { - return this.delegate.bodyToMono(elementClass); - } - - @Override - public Mono bodyToMono(ParameterizedTypeReference elementTypeRef) { - return this.delegate.bodyToMono(elementTypeRef); - } - - @Override - public Flux bodyToFlux(Class elementClass) { - return this.delegate.bodyToFlux(elementClass); - } - - @Override - public Flux bodyToFlux(ParameterizedTypeReference elementTypeRef) { - return this.delegate.bodyToFlux(elementTypeRef); - } - - @Override - public Mono releaseBody() { - return this.delegate.releaseBody(); - } - - @Override - public Mono> toBodilessEntity() { - return this.delegate.toBodilessEntity(); - } - - @Override - public Mono> toEntity(Class bodyType) { - return this.delegate.toEntity(bodyType); - } - - @Override - public Mono> toEntity(ParameterizedTypeReference bodyTypeReference) { - return this.delegate.toEntity(bodyTypeReference); - } - - @Override - public Mono>> toEntityList(Class elementClass) { - return this.delegate.toEntityList(elementClass); - } - - @Override - public Mono>> toEntityList(ParameterizedTypeReference elementTypeRef) { - return this.delegate.toEntityList(elementTypeRef); - } - - @Override - public Mono createException() { - return this.delegate.createException(); - } - - @Override - public Mono createError() { - return this.delegate.createError(); - } - - @Override - public String logPrefix() { - return this.delegate.logPrefix(); - } - /** * Implementation of the {@code Headers} interface that can be subclassed * to adapt the headers in a * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction exchange filter function}. * All methods default to calling through to the wrapped request. */ - public static class HeadersWrapper implements ClientResponse.Headers { - - private final Headers headers; - + @Mixin + public static class HeadersWrapper extends HeadersWrapperForwarder implements ClientResponse.Headers { /** * Create a new {@code HeadersWrapper} that wraps the given request. + * * @param headers the headers to wrap */ public HeadersWrapper(Headers headers) { - this.headers = headers; - } - - - @Override - public OptionalLong contentLength() { - return this.headers.contentLength(); - } - - @Override - public Optional contentType() { - return this.headers.contentType(); - } - - @Override - public List header(String headerName) { - return this.headers.header(headerName); - } - - @Override - public HttpHeaders asHttpHeaders() { - return this.headers.asHttpHeaders(); + super(headers); } } - } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java index 2a0929f416aa..cd7c147c56fd 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java @@ -18,22 +18,18 @@ import java.net.URI; import java.nio.charset.StandardCharsets; -import java.security.Principal; -import java.time.Instant; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; -import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.springframework.context.ApplicationContext; -import org.springframework.context.i18n.LocaleContext; import org.springframework.core.ResolvableType; import org.springframework.core.codec.Hints; import org.springframework.core.io.buffer.DataBuffer; @@ -48,7 +44,6 @@ import org.springframework.http.codec.multipart.Part; import org.springframework.http.server.RequestPath; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; @@ -56,7 +51,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.reactive.accept.ApiVersionStrategy; import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebSession; import org.springframework.web.util.UriUtils; /** @@ -310,8 +304,8 @@ public Flux getBody() { } } - - private static class DelegatingServerWebExchange implements ServerWebExchange { + @Mixin + static class DelegatingServerWebExchange extends DelegatingServerWebExchangeForwarder implements ServerWebExchange { private static final ResolvableType FORM_DATA_TYPE = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class); @@ -329,25 +323,21 @@ private static class DelegatingServerWebExchange implements ServerWebExchange { private final Map attributes; - private final ServerWebExchange delegate; - private final Mono> formDataMono; private final Mono> multipartDataMono; DelegatingServerWebExchange(ServerHttpRequest request, Map attributes, - ServerWebExchange delegate, List> messageReaders) { - + ServerWebExchange delegate, List> messageReaders) { + super(delegate); this.request = request; this.attributes = attributes; - this.delegate = delegate; this.formDataMono = initFormData(request, messageReaders); this.multipartDataMono = initMultipartData(request, messageReaders); } @SuppressWarnings("unchecked") - private static Mono> initFormData(ServerHttpRequest request, - List> readers) { + private static Mono> initFormData(ServerHttpRequest request, List> readers) { try { MediaType contentType = request.getHeaders().getContentType(); @@ -368,7 +358,7 @@ private static Mono> initFormData(ServerHttpReques @SuppressWarnings("unchecked") private static Mono> initMultipartData(ServerHttpRequest request, - List> readers) { + List> readers) { try { MediaType contentType = request.getHeaders().getContentType(); @@ -406,68 +396,5 @@ public Mono> getFormData() { public Mono> getMultipartData() { return this.multipartDataMono; } - - // Delegating methods - - @Override - public ServerHttpResponse getResponse() { - return this.delegate.getResponse(); - } - - @Override - public Mono getSession() { - return this.delegate.getSession(); - } - - @Override - public Mono getPrincipal() { - return this.delegate.getPrincipal(); - } - - @Override - public LocaleContext getLocaleContext() { - return this.delegate.getLocaleContext(); - } - - @Override - public @Nullable ApplicationContext getApplicationContext() { - return this.delegate.getApplicationContext(); - } - - @Override - public boolean isNotModified() { - return this.delegate.isNotModified(); - } - - @Override - public boolean checkNotModified(Instant lastModified) { - return this.delegate.checkNotModified(lastModified); - } - - @Override - public boolean checkNotModified(String etag) { - return this.delegate.checkNotModified(etag); - } - - @Override - public boolean checkNotModified(@Nullable String etag, Instant lastModified) { - return this.delegate.checkNotModified(etag, lastModified); - } - - @Override - public String transformUrl(String url) { - return this.delegate.transformUrl(url); - } - - @Override - public void addUrlTransformer(Function transformer) { - this.delegate.addUrlTransformer(transformer); - } - - @Override - public String getLogPrefix() { - return this.delegate.getLogPrefix(); - } } - } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java index 24c3f48ab169..386f98ec7655 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java @@ -16,10 +16,6 @@ package org.springframework.web.reactive.function.server; -import java.net.InetSocketAddress; -import java.net.URI; -import java.security.Principal; -import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -32,35 +28,23 @@ import java.util.function.Function; import java.util.function.Predicate; +import guru.mocker.annotation.mixin.Mixin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.multipart.Part; import org.springframework.http.server.PathContainer; import org.springframework.http.server.RequestPath; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.MimeTypeUtils; -import org.springframework.util.MultiValueMap; import org.springframework.web.accept.ApiVersionHolder; -import org.springframework.web.bind.WebDataBinder; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.accept.ApiVersionStrategy; -import org.springframework.web.reactive.function.BodyExtractor; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebSession; -import org.springframework.web.util.UriBuilder; import org.springframework.web.util.UriUtils; import org.springframework.web.util.pattern.PathPattern; import org.springframework.web.util.pattern.PathPatternParser; @@ -1223,181 +1207,11 @@ public String toString() { } } - - - private abstract static class DelegatingServerRequest implements ServerRequest { - - private final ServerRequest delegate; - + @Mixin + abstract static class DelegatingServerRequest extends DelegatingServerRequestForwarder implements ServerRequest { protected DelegatingServerRequest(ServerRequest delegate) { - Assert.notNull(delegate, "Delegate must not be null"); - this.delegate = delegate; - } - - @Override - public HttpMethod method() { - return this.delegate.method(); - } - - @Override - public URI uri() { - return this.delegate.uri(); - } - - @Override - public UriBuilder uriBuilder() { - return this.delegate.uriBuilder(); - } - - @Override - public String path() { - return this.delegate.path(); - } - - @Override - public RequestPath requestPath() { - return this.delegate.requestPath(); - } - - @Override - public Headers headers() { - return this.delegate.headers(); - } - - @Override - public MultiValueMap cookies() { - return this.delegate.cookies(); - } - - @Override - public Optional remoteAddress() { - return this.delegate.remoteAddress(); - } - - @Override - public Optional localAddress() { - return this.delegate.localAddress(); - } - - @Override - public List> messageReaders() { - return this.delegate.messageReaders(); - } - - @Override - public @Nullable ApiVersionStrategy apiVersionStrategy() { - return this.delegate.apiVersionStrategy(); - } - - @Override - public T body(BodyExtractor extractor) { - return this.delegate.body(extractor); - } - - @Override - public T body(BodyExtractor extractor, Map hints) { - return this.delegate.body(extractor, hints); - } - - @Override - public Mono bodyToMono(Class elementClass) { - return this.delegate.bodyToMono(elementClass); - } - - @Override - public Mono bodyToMono(ParameterizedTypeReference typeReference) { - return this.delegate.bodyToMono(typeReference); - } - - @Override - public Flux bodyToFlux(Class elementClass) { - return this.delegate.bodyToFlux(elementClass); - } - - @Override - public Flux bodyToFlux(ParameterizedTypeReference typeReference) { - return this.delegate.bodyToFlux(typeReference); - } - - @Override - public Mono bind(Class bindType) { - return this.delegate.bind(bindType); - } - - @Override - public Mono bind(Class bindType, Consumer dataBinderCustomizer) { - return this.delegate.bind(bindType, dataBinderCustomizer); - } - - @Override - public Optional attribute(String name) { - return this.delegate.attribute(name); - } - - @Override - public Map attributes() { - return this.delegate.attributes(); - } - - @Override - public Optional queryParam(String name) { - return this.delegate.queryParam(name); - } - - @Override - public MultiValueMap queryParams() { - return this.delegate.queryParams(); - } - - @Override - public String pathVariable(String name) { - return this.delegate.pathVariable(name); - } - - @Override - public Map pathVariables() { - return this.delegate.pathVariables(); - } - - @Override - public Mono session() { - return this.delegate.session(); - } - - @Override - public Mono principal() { - return this.delegate.principal(); - } - - @Override - public Mono> formData() { - return this.delegate.formData(); - } - - @Override - public Mono> multipartData() { - return this.delegate.multipartData(); - } - - @Override - public ServerWebExchange exchange() { - return this.delegate.exchange(); - } - - @Override - public Mono checkNotModified(Instant lastModified) { - return this.delegate.checkNotModified(lastModified); - } - - @Override - public Mono checkNotModified(String etag) { - return this.delegate.checkNotModified(etag); - } - - @Override - public Mono checkNotModified(Instant lastModified, String etag) { - return this.delegate.checkNotModified(lastModified, etag); + super(delegate); } @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java index e1d469a64193..0148dfd822d9 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -27,6 +26,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; +import guru.mocker.annotation.mixin.Mixin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import reactor.core.publisher.Flux; @@ -35,10 +35,8 @@ import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; -import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.util.Assert; -import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; @@ -1436,23 +1434,11 @@ public RouterFunction withAttributes(Consumer> attributes } } - - private static class HandlerStrategiesResponseContext implements ServerResponse.Context { - - private final HandlerStrategies strategies; + @Mixin + static class HandlerStrategiesResponseContext extends HandlerStrategiesResponseContextForwarder implements ServerResponse.Context { public HandlerStrategiesResponseContext(HandlerStrategies strategies) { - this.strategies = strategies; - } - - @Override - public List> messageWriters() { - return this.strategies.messageWriters(); - } - - @Override - public List viewResolvers() { - return this.strategies.viewResolvers(); + super(strategies); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerRequestWrapper.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerRequestWrapper.java index 9c5b92d0ae76..09b5a15ef47a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerRequestWrapper.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/support/ServerRequestWrapper.java @@ -16,40 +16,9 @@ package org.springframework.web.reactive.function.server.support; -import java.net.InetSocketAddress; -import java.net.URI; -import java.nio.charset.Charset; -import java.security.Principal; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.OptionalLong; -import java.util.function.Consumer; +import guru.mocker.annotation.mixin.Mixin; -import org.jspecify.annotations.Nullable; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpCookie; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpRange; -import org.springframework.http.MediaType; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.multipart.Part; -import org.springframework.http.server.RequestPath; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.util.Assert; -import org.springframework.util.MultiValueMap; -import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.reactive.accept.ApiVersionStrategy; -import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebSession; -import org.springframework.web.util.UriBuilder; /** * Implementation of the {@link ServerRequest} interface that can be subclassed @@ -60,176 +29,22 @@ * @author Arjen Poutsma * @since 5.0 */ -public class ServerRequestWrapper implements ServerRequest { - - private final ServerRequest delegate; - +@Mixin +public class ServerRequestWrapper extends ServerRequestWrapperForwarder implements ServerRequest { /** * Create a new {@code ServerRequestWrapper} that wraps the given request. * @param delegate the request to wrap */ public ServerRequestWrapper(ServerRequest delegate) { - Assert.notNull(delegate, "Delegate must not be null"); - this.delegate = delegate; + super(delegate); } - /** * Return the wrapped request. */ public ServerRequest request() { - return this.delegate; - } - - @Override - public HttpMethod method() { - return this.delegate.method(); - } - - @Override - public URI uri() { - return this.delegate.uri(); - } - - @Override - public UriBuilder uriBuilder() { - return this.delegate.uriBuilder(); - } - - @Override - public String path() { - return this.delegate.path(); - } - - @Override - public RequestPath requestPath() { - return this.delegate.requestPath(); - } - - @Override - public Headers headers() { - return this.delegate.headers(); - } - - @Override - public MultiValueMap cookies() { - return this.delegate.cookies(); - } - - @Override - public Optional remoteAddress() { - return this.delegate.remoteAddress(); - } - - @Override - public Optional localAddress() { - return this.delegate.localAddress(); - } - - @Override - public List> messageReaders() { - return this.delegate.messageReaders(); - } - - @Override - public @Nullable ApiVersionStrategy apiVersionStrategy() { - return this.delegate.apiVersionStrategy(); - } - - @Override - public T body(BodyExtractor extractor) { - return this.delegate.body(extractor); - } - - @Override - public T body(BodyExtractor extractor, Map hints) { - return this.delegate.body(extractor, hints); - } - - @Override - public Mono bodyToMono(Class elementClass) { - return this.delegate.bodyToMono(elementClass); - } - - @Override - public Mono bodyToMono(ParameterizedTypeReference typeReference) { - return this.delegate.bodyToMono(typeReference); - } - - @Override - public Flux bodyToFlux(Class elementClass) { - return this.delegate.bodyToFlux(elementClass); - } - - @Override - public Flux bodyToFlux(ParameterizedTypeReference typeReference) { - return this.delegate.bodyToFlux(typeReference); - } - - @Override - public Mono bind(Class bindType) { - return this.delegate.bind(bindType); - } - - @Override - public Mono bind(Class bindType, Consumer dataBinderCustomizer) { - return this.delegate.bind(bindType, dataBinderCustomizer); - } - - @Override - public Optional attribute(String name) { - return this.delegate.attribute(name); - } - - @Override - public Map attributes() { - return this.delegate.attributes(); - } - - @Override - public Optional queryParam(String name) { - return this.delegate.queryParam(name); - } - - @Override - public MultiValueMap queryParams() { - return this.delegate.queryParams(); - } - - @Override - public String pathVariable(String name) { - return this.delegate.pathVariable(name); - } - - @Override - public Map pathVariables() { - return this.delegate.pathVariables(); - } - - @Override - public Mono session() { - return this.delegate.session(); - } - - @Override - public Mono principal() { - return this.delegate.principal(); - } - - @Override - public Mono> formData() { - return this.delegate.formData(); - } - - @Override - public Mono> multipartData() { - return this.delegate.multipartData(); - } - - @Override - public ServerWebExchange exchange() { - return this.delegate.exchange(); + return delegate; } /** @@ -238,63 +53,16 @@ public ServerWebExchange exchange() { * {@link org.springframework.web.reactive.function.server.HandlerFilterFunction handler filter function}. * All methods default to calling through to the wrapped headers. */ - public static class HeadersWrapper implements ServerRequest.Headers { - - private final Headers headers; + @Mixin + public static class HeadersWrapper extends HeadersWrapperForwarder implements ServerRequest.Headers { /** * Create a new {@code HeadersWrapper} that wraps the given request. + * * @param headers the headers to wrap */ public HeadersWrapper(Headers headers) { - Assert.notNull(headers, "Headers must not be null"); - this.headers = headers; - } - - @Override - public List accept() { - return this.headers.accept(); - } - - @Override - public List acceptCharset() { - return this.headers.acceptCharset(); - } - - @Override - public List acceptLanguage() { - return this.headers.acceptLanguage(); - } - - @Override - public OptionalLong contentLength() { - return this.headers.contentLength(); - } - - @Override - public Optional contentType() { - return this.headers.contentType(); - } - - @Override - public @Nullable InetSocketAddress host() { - return this.headers.host(); - } - - @Override - public List range() { - return this.headers.range(); - } - - @Override - public List header(String headerName) { - return this.headers.header(headerName); - } - - @Override - public HttpHeaders asHttpHeaders() { - return this.headers.asHttpHeaders(); + super(headers); } } - } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java index 000af7a8e8e9..023bfdd232e7 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java @@ -16,14 +16,7 @@ package org.springframework.web.reactive.resource; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.Charset; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -32,6 +25,7 @@ import java.util.Locale; import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; @@ -200,91 +194,34 @@ static List parseAcceptEncoding(ServerWebExchange exchange) { } + @Mixin(grandparent = AbstractResource.class) + static sealed class EncodedResourceInterForwarder extends EncodedResourceForwarder implements HttpResource permits EncodedResource { + public EncodedResourceInterForwarder(Resource encoded) { + super(encoded); + } + + /** + * To be overridden in the child class. + * @return a dummy new http headers + */ + @Override + public HttpHeaders getResponseHeaders() { + return new HttpHeaders(); + } + } /** * An encoded {@link HttpResource}. */ - static final class EncodedResource extends AbstractResource implements HttpResource { + static final class EncodedResource extends EncodedResourceInterForwarder { private final Resource original; private final String coding; - private final Resource encoded; - EncodedResource(Resource original, String coding, String extension) throws IOException { + super(original.createRelative(original.getFilename() + extension)); this.original = original; this.coding = coding; - this.encoded = original.createRelative(original.getFilename() + extension); - } - - @Override - public boolean exists() { - return this.encoded.exists(); - } - - @Override - public boolean isReadable() { - return this.encoded.isReadable(); - } - - @Override - public boolean isOpen() { - return this.encoded.isOpen(); - } - - @Override - public boolean isFile() { - return this.encoded.isFile(); - } - - @Override - public URL getURL() throws IOException { - return this.encoded.getURL(); - } - - @Override - public URI getURI() throws IOException { - return this.encoded.getURI(); - } - - @Override - public File getFile() throws IOException { - return this.encoded.getFile(); - } - - @Override - public Path getFilePath() throws IOException { - return this.encoded.getFilePath(); - } - - @Override - public InputStream getInputStream() throws IOException { - return this.encoded.getInputStream(); - } - - @Override - public ReadableByteChannel readableChannel() throws IOException { - return this.encoded.readableChannel(); - } - - @Override - public byte[] getContentAsByteArray() throws IOException { - return this.encoded.getContentAsByteArray(); - } - - @Override - public String getContentAsString(Charset charset) throws IOException { - return this.encoded.getContentAsString(charset); - } - - @Override - public long contentLength() throws IOException { - return this.encoded.contentLength(); - } - - @Override - public long lastModified() throws IOException { - return this.encoded.lastModified(); } @Override @@ -297,11 +234,6 @@ public Resource createRelative(String relativePath) throws IOException { return this.original.getFilename(); } - @Override - public String getDescription() { - return this.encoded.getDescription(); - } - @Override public HttpHeaders getResponseHeaders() { HttpHeaders headers; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java index bdf475b0a20b..92fc86bb4487 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java @@ -16,14 +16,6 @@ package org.springframework.web.reactive.resource; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.Charset; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -31,6 +23,7 @@ import java.util.List; import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; @@ -240,103 +233,16 @@ protected Mono resolveUrlPathInternal(String resourceUrlPath, return null; } - - private static class FileNameVersionedResource extends AbstractResource implements HttpResource { - - private final Resource original; + @Mixin(grandparent = AbstractResource.class) + static class FileNameVersionedResource extends FileNameVersionedResourceForwarder implements HttpResource { private final String version; public FileNameVersionedResource(Resource original, String version) { - this.original = original; + super(original, version); this.version = version; } - @Override - public boolean exists() { - return this.original.exists(); - } - - @Override - public boolean isReadable() { - return this.original.isReadable(); - } - - @Override - public boolean isOpen() { - return this.original.isOpen(); - } - - @Override - public boolean isFile() { - return this.original.isFile(); - } - - @Override - public URL getURL() throws IOException { - return this.original.getURL(); - } - - @Override - public URI getURI() throws IOException { - return this.original.getURI(); - } - - @Override - public File getFile() throws IOException { - return this.original.getFile(); - } - - @Override - public Path getFilePath() throws IOException { - return this.original.getFilePath(); - } - - @Override - public InputStream getInputStream() throws IOException { - return this.original.getInputStream(); - } - - @Override - public ReadableByteChannel readableChannel() throws IOException { - return this.original.readableChannel(); - } - - @Override - public byte[] getContentAsByteArray() throws IOException { - return this.original.getContentAsByteArray(); - } - - @Override - public String getContentAsString(Charset charset) throws IOException { - return this.original.getContentAsString(charset); - } - - @Override - public long contentLength() throws IOException { - return this.original.contentLength(); - } - - @Override - public long lastModified() throws IOException { - return this.original.lastModified(); - } - - @Override - public Resource createRelative(String relativePath) throws IOException { - return this.original.createRelative(relativePath); - } - - @Override - public @Nullable String getFilename() { - return this.original.getFilename(); - } - - @Override - public String getDescription() { - return this.original.getDescription(); - } - @Override public HttpHeaders getResponseHeaders() { HttpHeaders headers = (this.original instanceof HttpResource hr ? hr.getResponseHeaders() : new HttpHeaders()); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/JettyWebSocketHandlerAdapter.java b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/JettyWebSocketHandlerAdapter.java index cf482a3caeca..440abc95aa0b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/JettyWebSocketHandlerAdapter.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/JettyWebSocketHandlerAdapter.java @@ -20,8 +20,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.function.Function; -import java.util.function.IntPredicate; +import guru.mocker.annotation.mixin.Mixin; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.Callback; import org.eclipse.jetty.websocket.api.Session; @@ -29,7 +29,6 @@ import org.springframework.core.io.buffer.CloseableDataBuffer; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.util.Assert; import org.springframework.web.reactive.socket.CloseStatus; import org.springframework.web.reactive.socket.WebSocketHandler; @@ -110,18 +109,11 @@ public void onWebSocketError(Throwable cause) { this.delegateSession.handleError(cause); } - - private static final class JettyCallbackDataBuffer implements CloseableDataBuffer { - - private final DataBuffer delegate; - - private final Callback callback; + @Mixin + static final class JettyCallbackDataBuffer extends JettyCallbackDataBufferForwarder implements CloseableDataBuffer { public JettyCallbackDataBuffer(DataBuffer delegate, Callback callback) { - Assert.notNull(delegate, "'delegate` must not be null"); - Assert.notNull(callback, "Callback must not be null"); - this.delegate = delegate; - this.callback = callback; + super(delegate, callback); } @Override @@ -129,38 +121,6 @@ public void close() { this.callback.succeed(); } - // delegation - - @Override - public DataBufferFactory factory() { - return this.delegate.factory(); - } - - @Override - public int indexOf(IntPredicate predicate, int fromIndex) { - return this.delegate.indexOf(predicate, fromIndex); - } - - @Override - public int lastIndexOf(IntPredicate predicate, int fromIndex) { - return this.delegate.lastIndexOf(predicate, fromIndex); - } - - @Override - public int readableByteCount() { - return this.delegate.readableByteCount(); - } - - @Override - public int writableByteCount() { - return this.delegate.writableByteCount(); - } - - @Override - public int capacity() { - return this.delegate.capacity(); - } - @Override @Deprecated(since = "6.0") public DataBuffer capacity(int capacity) { @@ -168,86 +128,6 @@ public DataBuffer capacity(int capacity) { return this; } - @Override - public DataBuffer ensureWritable(int capacity) { - this.delegate.ensureWritable(capacity); - return this; - } - - @Override - public int readPosition() { - return this.delegate.readPosition(); - } - - @Override - public DataBuffer readPosition(int readPosition) { - this.delegate.readPosition(readPosition); - return this; - } - - @Override - public int writePosition() { - return this.delegate.writePosition(); - } - - @Override - public DataBuffer writePosition(int writePosition) { - this.delegate.writePosition(writePosition); - return this; - } - - @Override - public byte getByte(int index) { - return this.delegate.getByte(index); - } - - @Override - public byte read() { - return this.delegate.read(); - } - - @Override - public DataBuffer read(byte[] destination) { - this.delegate.read(destination); - return this; - } - - @Override - public DataBuffer read(byte[] destination, int offset, int length) { - this.delegate.read(destination, offset, length); - return this; - } - - @Override - public DataBuffer write(byte b) { - this.delegate.write(b); - return this; - } - - @Override - public DataBuffer write(byte[] source) { - this.delegate.write(source); - return this; - } - - @Override - public DataBuffer write(byte[] source, int offset, int length) { - this.delegate.write(source, offset, length); - return this; - } - - @Override - public DataBuffer write(DataBuffer... buffers) { - this.delegate.write(buffers); - return this; - } - - @Override - public DataBuffer write(ByteBuffer... buffers) { - this.delegate.write(buffers); - return this; - } - @Override @Deprecated(since = "6.0") public DataBuffer slice(int index, int length) { @@ -279,21 +159,6 @@ public ByteBuffer toByteBuffer(int index, int length) { return this.delegate.toByteBuffer(index, length); } - @Override - public void toByteBuffer(int srcPos, ByteBuffer dest, int destPos, int length) { - this.delegate.toByteBuffer(srcPos, dest, destPos, length); - } - - @Override - public ByteBufferIterator readableByteBuffers() { - return this.delegate.readableByteBuffers(); - } - - @Override - public ByteBufferIterator writableByteBuffers() { - return this.delegate.writableByteBuffers(); - } - @Override public String toString(int index, int length, Charset charset) { return this.delegate.toString(index, length, charset); diff --git a/spring-webmvc/spring-webmvc.gradle b/spring-webmvc/spring-webmvc.gradle index 194278ad7c07..e9fef03cb2d8 100644 --- a/spring-webmvc/spring-webmvc.gradle +++ b/spring-webmvc/spring-webmvc.gradle @@ -4,6 +4,9 @@ apply plugin: "kotlin" apply plugin: "kotlinx-serialization" dependencies { + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + annotationProcessor(project(":framework-annotation-processor")) api(project(":spring-aop")) api(project(":spring-beans")) api(project(":spring-context")) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java index 084aeb46658f..31189e62b475 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java @@ -18,20 +18,13 @@ import java.util.List; -import org.jspecify.annotations.Nullable; +import guru.mocker.annotation.mixin.Mixin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.HttpMessageConverters; import org.springframework.util.CollectionUtils; -import org.springframework.validation.MessageCodesResolver; -import org.springframework.validation.Validator; import org.springframework.web.ErrorResponse; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.HandlerMethodReturnValueHandler; -import org.springframework.web.servlet.HandlerExceptionResolver; /** * A subclass of {@code WebMvcConfigurationSupport} that detects and delegates @@ -43,126 +36,43 @@ * @since 3.1 */ @Configuration(proxyBeanMethods = false) -public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { +public class DelegatingWebMvcConfiguration extends DelegatingWebMvcConfigurationForwarder implements WebMvcConfigurer { - private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); - - - @Autowired(required = false) - public void setConfigurers(List configurers) { - if (!CollectionUtils.isEmpty(configurers)) { - this.configurers.addWebMvcConfigurers(configurers); - } - } - - - @Override - protected void configurePathMatch(PathMatchConfigurer configurer) { - this.configurers.configurePathMatch(configurer); + @Mixin(grandparent = WebMvcConfigurationSupport.class) + public DelegatingWebMvcConfiguration(WebMvcConfigurerComposite configurers) { + super(configurers); } - @Override - protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) { - this.configurers.configureContentNegotiation(configurer); - } - - @Override - protected void configureApiVersioning(ApiVersionConfigurer configurer) { - this.configurers.configureApiVersioning(configurer); - } - - @Override - protected void configureAsyncSupport(AsyncSupportConfigurer configurer) { - this.configurers.configureAsyncSupport(configurer); + public DelegatingWebMvcConfiguration() { + this(new WebMvcConfigurerComposite()); } - @Override - protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { - this.configurers.configureDefaultServletHandling(configurer); - } - - @Override - protected void addFormatters(FormatterRegistry registry) { - this.configurers.addFormatters(registry); - } - - @Override - protected void addInterceptors(InterceptorRegistry registry) { - this.configurers.addInterceptors(registry); - } - - @Override - protected void addResourceHandlers(ResourceHandlerRegistry registry) { - this.configurers.addResourceHandlers(registry); - } - - @Override - protected void addCorsMappings(CorsRegistry registry) { - this.configurers.addCorsMappings(registry); - } - - @Override - protected void addViewControllers(ViewControllerRegistry registry) { - this.configurers.addViewControllers(registry); - } - - @Override - protected void configureViewResolvers(ViewResolverRegistry registry) { - this.configurers.configureViewResolvers(registry); - } - - @Override - protected void addArgumentResolvers(List argumentResolvers) { - this.configurers.addArgumentResolvers(argumentResolvers); - } - - @Override - protected void addReturnValueHandlers(List returnValueHandlers) { - this.configurers.addReturnValueHandlers(returnValueHandlers); - } - - @Override - protected void configureMessageConverters(HttpMessageConverters.ServerBuilder builder) { - this.configurers.configureMessageConverters(builder); + @Autowired(required = false) + public void setConfigurers(List configurersList) { + if (!CollectionUtils.isEmpty(configurersList)) { + configurers.addWebMvcConfigurers(configurersList); + } } + // Manually implement deprecated methods (Mixin skips deprecated methods intentionally) @Override @Deprecated(since = "7.0", forRemoval = true) @SuppressWarnings("removal") - protected void configureMessageConverters(List> converters) { - this.configurers.configureMessageConverters(converters); + public void configureMessageConverters(List> converters) { + configurers.configureMessageConverters(converters); } @Override @Deprecated(since = "7.0", forRemoval = true) @SuppressWarnings("removal") - protected void extendMessageConverters(List> converters) { - this.configurers.extendMessageConverters(converters); - } - - @Override - protected void configureHandlerExceptionResolvers(List exceptionResolvers) { - this.configurers.configureHandlerExceptionResolvers(exceptionResolvers); - } - - @Override - protected void extendHandlerExceptionResolvers(List exceptionResolvers) { - this.configurers.extendHandlerExceptionResolvers(exceptionResolvers); + public void extendMessageConverters(List> converters) { + configurers.extendMessageConverters(converters); } + // Override parent's protected method (Mixin generates interface method instead) @Override protected void configureErrorResponseInterceptors(List interceptors) { - this.configurers.addErrorResponseInterceptors(interceptors); - } - - @Override - protected @Nullable Validator getValidator() { - return this.configurers.getValidator(); - } - - @Override - protected @Nullable MessageCodesResolver getMessageCodesResolver() { - return this.configurers.getMessageCodesResolver(); + configurers.addErrorResponseInterceptors(interceptors); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java index b7c5ecc35974..9fd8d328606e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java @@ -16,14 +16,6 @@ package org.springframework.web.servlet.resource; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.Charset; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -31,10 +23,10 @@ import java.util.List; import java.util.Map; +import guru.mocker.annotation.mixin.Mixin; import jakarta.servlet.http.HttpServletRequest; import org.jspecify.annotations.Nullable; -import org.springframework.core.io.AbstractResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.util.AntPathMatcher; @@ -237,107 +229,18 @@ public VersionResourceResolver addVersionStrategy(VersionStrategy strategy, Stri } - private static class FileNameVersionedResource extends AbstractResource implements HttpResource { - - private final Resource original; - - private final String version; + static class FileNameVersionedResource extends FileNameVersionedResourceForwarder implements HttpResource { + @Mixin public FileNameVersionedResource(Resource original, String version) { - this.original = original; - this.version = version; - } - - @Override - public boolean exists() { - return this.original.exists(); - } - - @Override - public boolean isReadable() { - return this.original.isReadable(); - } - - @Override - public boolean isOpen() { - return this.original.isOpen(); - } - - @Override - public boolean isFile() { - return this.original.isFile(); - } - - @Override - public URL getURL() throws IOException { - return this.original.getURL(); - } - - @Override - public URI getURI() throws IOException { - return this.original.getURI(); - } - - @Override - public File getFile() throws IOException { - return this.original.getFile(); - } - - @Override - public Path getFilePath() throws IOException { - return this.original.getFilePath(); - } - - @Override - public InputStream getInputStream() throws IOException { - return this.original.getInputStream(); - } - - @Override - public ReadableByteChannel readableChannel() throws IOException { - return this.original.readableChannel(); - } - - @Override - public byte[] getContentAsByteArray() throws IOException { - return this.original.getContentAsByteArray(); - } - - @Override - public String getContentAsString(Charset charset) throws IOException { - return this.original.getContentAsString(charset); - } - - @Override - public long contentLength() throws IOException { - return this.original.contentLength(); - } - - @Override - public long lastModified() throws IOException { - return this.original.lastModified(); - } - - @Override - public Resource createRelative(String relativePath) throws IOException { - return this.original.createRelative(relativePath); - } - - @Override - public @Nullable String getFilename() { - return this.original.getFilename(); - } - - @Override - public String getDescription() { - return this.original.getDescription(); + super(original, version); } @Override public HttpHeaders getResponseHeaders() { - HttpHeaders headers = (this.original instanceof HttpResource httpResource ? + HttpHeaders headers = (original instanceof HttpResource httpResource ? httpResource.getResponseHeaders() : new HttpHeaders()); - headers.setETag("W/\"" + this.version + "\""); + headers.setETag("W/\"" + version + "\""); return headers; } } diff --git a/spring-websocket/spring-websocket.gradle b/spring-websocket/spring-websocket.gradle index 268e2b29db06..a98b0eca5953 100644 --- a/spring-websocket/spring-websocket.gradle +++ b/spring-websocket/spring-websocket.gradle @@ -1,6 +1,9 @@ description = "Spring WebSocket" dependencies { + compileOnly("guru.mocker.annotation:mixin-annotation:${mixinAnnotationVersion}") + annotationProcessor("guru.mocker.annotation:mixin-annotation-processor:${mixinAnnotationVersion}") + annotationProcessor(project(":framework-annotation-processor")) api(project(":spring-context")) api(project(":spring-core")) api(project(":spring-web")) diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketHandlerDecorator.java b/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketHandlerDecorator.java index 2dbcb15e4958..21e750653f76 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketHandlerDecorator.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketHandlerDecorator.java @@ -16,11 +16,10 @@ package org.springframework.web.socket.handler; +import guru.mocker.annotation.mixin.Mixin; + import org.springframework.util.Assert; -import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.WebSocketMessage; -import org.springframework.web.socket.WebSocketSession; /** * Wraps another {@link org.springframework.web.socket.WebSocketHandler} @@ -33,23 +32,20 @@ * @author Rossen Stoyanchev * @since 4.0 */ -public class WebSocketHandlerDecorator implements WebSocketHandler { - - private final WebSocketHandler delegate; - +public class WebSocketHandlerDecorator extends WebSocketHandlerDecoratorForwarder implements WebSocketHandler { + @Mixin public WebSocketHandlerDecorator(WebSocketHandler delegate) { + super(delegate); Assert.notNull(delegate, "Delegate must not be null"); - this.delegate = delegate; } - public WebSocketHandler getDelegate() { - return this.delegate; + return delegate; } public WebSocketHandler getLastHandler() { - WebSocketHandler result = this.delegate; + WebSocketHandler result = delegate; while (result instanceof WebSocketHandlerDecorator webSocketHandlerDecorator) { result = webSocketHandlerDecorator.getDelegate(); } @@ -65,34 +61,9 @@ public static WebSocketHandler unwrap(WebSocketHandler handler) { } } - @Override - public void afterConnectionEstablished(WebSocketSession session) throws Exception { - this.delegate.afterConnectionEstablished(session); - } - - @Override - public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { - this.delegate.handleMessage(session, message); - } - - @Override - public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { - this.delegate.handleTransportError(session, exception); - } - - @Override - public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { - this.delegate.afterConnectionClosed(session, closeStatus); - } - - @Override - public boolean supportsPartialMessages() { - return this.delegate.supportsPartialMessages(); - } - @Override public String toString() { - return getClass().getSimpleName() + " [delegate=" + this.delegate + "]"; + return getClass().getSimpleName() + " [delegate=" + delegate + "]"; } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketSessionDecorator.java b/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketSessionDecorator.java index 3647a831f2c1..848b75db9271 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketSessionDecorator.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/handler/WebSocketSessionDecorator.java @@ -16,20 +16,10 @@ package org.springframework.web.socket.handler; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.URI; -import java.security.Principal; -import java.util.List; -import java.util.Map; -import org.jspecify.annotations.Nullable; +import guru.mocker.annotation.mixin.Mixin; -import org.springframework.http.HttpHeaders; import org.springframework.util.Assert; -import org.springframework.web.socket.CloseStatus; -import org.springframework.web.socket.WebSocketExtension; -import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; /** @@ -43,23 +33,21 @@ * @author Rossen Stoyanchev * @since 4.0.3 */ -public class WebSocketSessionDecorator implements WebSocketSession { +public class WebSocketSessionDecorator extends WebSocketSessionDecoratorForwarder implements WebSocketSession { - private final WebSocketSession delegate; - - - public WebSocketSessionDecorator(WebSocketSession session) { - Assert.notNull(session, "Delegate WebSocketSessionSession is required"); - this.delegate = session; + @Mixin + public WebSocketSessionDecorator(WebSocketSession delegate) { + super(delegate); + Assert.notNull(delegate, "Delegate WebSocketSessionSession is required"); } public WebSocketSession getDelegate() { - return this.delegate; + return delegate; } public WebSocketSession getLastSession() { - WebSocketSession result = this.delegate; + WebSocketSession result = delegate; while (result instanceof WebSocketSessionDecorator webSocketSessionDecorator) { result = webSocketSessionDecorator.getDelegate(); } @@ -75,91 +63,6 @@ public static WebSocketSession unwrap(WebSocketSession session) { } } - @Override - public String getId() { - return this.delegate.getId(); - } - - @Override - public @Nullable URI getUri() { - return this.delegate.getUri(); - } - - @Override - public HttpHeaders getHandshakeHeaders() { - return this.delegate.getHandshakeHeaders(); - } - - @Override - public Map getAttributes() { - return this.delegate.getAttributes(); - } - - @Override - public @Nullable Principal getPrincipal() { - return this.delegate.getPrincipal(); - } - - @Override - public @Nullable InetSocketAddress getLocalAddress() { - return this.delegate.getLocalAddress(); - } - - @Override - public @Nullable InetSocketAddress getRemoteAddress() { - return this.delegate.getRemoteAddress(); - } - - @Override - public @Nullable String getAcceptedProtocol() { - return this.delegate.getAcceptedProtocol(); - } - - @Override - public List getExtensions() { - return this.delegate.getExtensions(); - } - - @Override - public void setTextMessageSizeLimit(int messageSizeLimit) { - this.delegate.setTextMessageSizeLimit(messageSizeLimit); - } - - @Override - public int getTextMessageSizeLimit() { - return this.delegate.getTextMessageSizeLimit(); - } - - @Override - public void setBinaryMessageSizeLimit(int messageSizeLimit) { - this.delegate.setBinaryMessageSizeLimit(messageSizeLimit); - } - - @Override - public int getBinaryMessageSizeLimit() { - return this.delegate.getBinaryMessageSizeLimit(); - } - - @Override - public boolean isOpen() { - return this.delegate.isOpen(); - } - - @Override - public void sendMessage(WebSocketMessage message) throws IOException { - this.delegate.sendMessage(message); - } - - @Override - public void close() throws IOException { - this.delegate.close(); - } - - @Override - public void close(CloseStatus status) throws IOException { - this.delegate.close(status); - } - @Override public String toString() { return getClass().getSimpleName() + " [delegate=" + this.delegate + "]";