Skip to content

Commit

Permalink
Merge branch 'spring-projects:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
lucky8987 authored Nov 25, 2024
2 parents 8987ed1 + 64f93d5 commit 0bf4234
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 198 deletions.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
Expand All @@ -18,7 +18,6 @@

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -107,18 +106,22 @@ public static BeanRegistrationAotContribution processAheadOfTime(RegisteredBean
Set<Class<?>> validatedClasses = new HashSet<>();
Set<Class<? extends ConstraintValidator<?, ?>>> constraintValidatorClasses = new HashSet<>();

processAheadOfTime(beanClass, validatedClasses, constraintValidatorClasses);
processAheadOfTime(beanClass, new HashSet<>(), validatedClasses, constraintValidatorClasses);

if (!validatedClasses.isEmpty() || !constraintValidatorClasses.isEmpty()) {
return new AotContribution(validatedClasses, constraintValidatorClasses);
}
return null;
}

private static void processAheadOfTime(Class<?> clazz, Collection<Class<?>> validatedClasses,
Collection<Class<? extends ConstraintValidator<?, ?>>> constraintValidatorClasses) {
private static void processAheadOfTime(Class<?> clazz, Set<Class<?>> visitedClasses, Set<Class<?>> validatedClasses,
Set<Class<? extends ConstraintValidator<?, ?>>> constraintValidatorClasses) {

Assert.notNull(validator, "Validator cannot be null");

Assert.notNull(validator, "Validator can't be null");
if (!visitedClasses.add(clazz)) {
return;
}

BeanDescriptor descriptor;
try {
Expand Down Expand Up @@ -149,12 +152,12 @@ else if (ex instanceof TypeNotPresentException) {

ReflectionUtils.doWithFields(clazz, field -> {
Class<?> type = field.getType();
if (Iterable.class.isAssignableFrom(type) || List.class.isAssignableFrom(type) || Optional.class.isAssignableFrom(type)) {
if (Iterable.class.isAssignableFrom(type) || Optional.class.isAssignableFrom(type)) {
ResolvableType resolvableType = ResolvableType.forField(field);
Class<?> genericType = resolvableType.getGeneric(0).toClass();
if (shouldProcess(genericType)) {
validatedClasses.add(clazz);
processAheadOfTime(genericType, validatedClasses, constraintValidatorClasses);
processAheadOfTime(genericType, visitedClasses, validatedClasses, constraintValidatorClasses);
}
}
if (Map.class.isAssignableFrom(type)) {
Expand All @@ -163,11 +166,11 @@ else if (ex instanceof TypeNotPresentException) {
Class<?> valueGenericType = resolvableType.getGeneric(1).toClass();
if (shouldProcess(keyGenericType)) {
validatedClasses.add(clazz);
processAheadOfTime(keyGenericType, validatedClasses, constraintValidatorClasses);
processAheadOfTime(keyGenericType, visitedClasses, validatedClasses, constraintValidatorClasses);
}
if (shouldProcess(valueGenericType)) {
validatedClasses.add(clazz);
processAheadOfTime(valueGenericType, validatedClasses, constraintValidatorClasses);
processAheadOfTime(valueGenericType, visitedClasses, validatedClasses, constraintValidatorClasses);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
Expand All @@ -22,6 +22,8 @@
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
Expand All @@ -31,6 +33,8 @@
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.internal.constraintvalidators.bv.PatternValidator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.MemberCategory;
Expand Down Expand Up @@ -121,6 +125,15 @@ void shouldProcessTransitiveGenericTypeLevelConstraint() {
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}

@ParameterizedTest // gh-33936
@ValueSource(classes = {BeanWithRecursiveIterable.class, BeanWithRecursiveMap.class, BeanWithRecursiveOptional.class})
void shouldProcessRecursiveGenericsWithoutInfiniteRecursion(Class<?> beanClass) {
process(beanClass);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(1);
assertThat(RuntimeHintsPredicates.reflection().onType(beanClass)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
}

private void process(Class<?> beanClass) {
BeanRegistrationAotContribution contribution = createContribution(beanClass);
if (contribution != null) {
Expand Down Expand Up @@ -244,4 +257,16 @@ public void setExclude(List<Exclude> exclude) {
}
}

static class BeanWithRecursiveIterable {
Iterable<BeanWithRecursiveIterable> iterable;
}

static class BeanWithRecursiveMap {
Map<BeanWithRecursiveMap, BeanWithRecursiveMap> map;
}

static class BeanWithRecursiveOptional {
Optional<BeanWithRecursiveOptional> optional;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,10 @@ public String getContentAsString(Charset fallbackCharset) throws UnsupportedEnco

@Override
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
if (!this.committed) {
this.contentLength = contentLength;
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
}
}

/**
Expand All @@ -334,8 +336,10 @@ public int getContentLength() {

@Override
public void setContentLengthLong(long contentLength) {
this.contentLength = contentLength;
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
if (!this.committed) {
this.contentLength = contentLength;
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
}
}

public long getContentLengthLong() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
* @author Vedran Pavic
* @since 1.0.2
*/
@SuppressWarnings("deprecation")
public class MockHttpSession implements HttpSession {

/**
Expand Down Expand Up @@ -240,6 +239,12 @@ public boolean isNew() {
return this.isNew;
}

@Override
public Accessor getAccessor() {
return sessionConsumer -> sessionConsumer.accept(MockHttpSession.this);
}


/**
* Serialize the attributes of this session into an object that can be
* turned into a byte array with standard Java serialization.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
Expand All @@ -38,6 +39,7 @@

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
Expand All @@ -58,6 +60,7 @@
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @author Brian Clozel
* @since 5.0
*/
class ServletServerHttpRequest extends AbstractServerHttpRequest {
Expand All @@ -75,7 +78,7 @@ class ServletServerHttpRequest extends AbstractServerHttpRequest {

private final DataBufferFactory bufferFactory;

private final byte[] buffer;
private final int bufferSize;

private final AsyncListener asyncListener;

Expand All @@ -99,7 +102,7 @@ public ServletServerHttpRequest(MultiValueMap<String, String> headers, HttpServl

this.request = request;
this.bufferFactory = bufferFactory;
this.buffer = new byte[bufferSize];
this.bufferSize = bufferSize;

this.asyncListener = new RequestAsyncListener();

Expand Down Expand Up @@ -275,20 +278,31 @@ protected final ServletInputStream getInputStream() {
* or {@link #EOF_BUFFER} if the input stream returned -1.
*/
DataBuffer readFromInputStream() throws IOException {
int read = this.inputStream.read(this.buffer);
logBytesRead(read);

if (read > 0) {
DataBuffer dataBuffer = this.bufferFactory.allocateBuffer(read);
dataBuffer.write(this.buffer, 0, read);
return dataBuffer;
DataBuffer dataBuffer = this.bufferFactory.allocateBuffer(this.bufferSize);
int read = -1;
try {
try (DataBuffer.ByteBufferIterator iterator = dataBuffer.writableByteBuffers()) {
Assert.state(iterator.hasNext(), "No ByteBuffer available");
ByteBuffer byteBuffer = iterator.next();
read = this.inputStream.read(byteBuffer);
}
logBytesRead(read);
if (read > 0) {
dataBuffer.writePosition(read);
return dataBuffer;
}
else if (read == -1) {
return EOF_BUFFER;
}
else {
return AbstractListenerReadPublisher.EMPTY_BUFFER;
}
}

if (read == -1) {
return EOF_BUFFER;
finally {
if (read <= 0) {
DataBufferUtils.release(dataBuffer);
}
}

return AbstractListenerReadPublisher.EMPTY_BUFFER;
}

protected final void logBytesRead(int read) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.springframework.http.server.reactive;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import jakarta.servlet.AsyncContext;
Expand Down Expand Up @@ -45,6 +45,7 @@
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @author Brian Clozel
* @since 5.0
*/
class ServletServerHttpResponse extends AbstractListenerServerHttpResponse {
Expand Down Expand Up @@ -222,15 +223,15 @@ protected final ServletOutputStream getOutputStream() {
*/
protected int writeToOutputStream(DataBuffer dataBuffer) throws IOException {
ServletOutputStream outputStream = this.outputStream;
InputStream input = dataBuffer.asInputStream();
int bytesWritten = 0;
byte[] buffer = new byte[this.bufferSize];
int bytesRead;
while (outputStream.isReady() && (bytesRead = input.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
bytesWritten += bytesRead;
int len = 0;
try (DataBuffer.ByteBufferIterator iterator = dataBuffer.readableByteBuffers()) {
while (iterator.hasNext() && outputStream.isReady()) {
ByteBuffer byteBuffer = iterator.next();
len += byteBuffer.remaining();
outputStream.write(byteBuffer);
}
}
return bytesWritten;
return len;
}

private void flush() throws IOException {
Expand Down
Loading

0 comments on commit 0bf4234

Please sign in to comment.