Skip to content

Commit 6f6e25b

Browse files
committed
Merge branch '6.1.x'
2 parents ddf5521 + 65e1337 commit 6f6e25b

File tree

6 files changed

+145
-72
lines changed

6 files changed

+145
-72
lines changed

spring-aspects/src/test/java/org/springframework/beans/factory/aspectj/SpringConfiguredWithAutoProxyingTests.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020

2121
import org.springframework.context.support.ClassPathXmlApplicationContext;
2222

23-
public class SpringConfiguredWithAutoProxyingTests {
23+
/**
24+
* @author Ramnivas Laddad
25+
* @author Juergen Hoeller
26+
*/
27+
class SpringConfiguredWithAutoProxyingTests {
2428

2529
@Test
2630
void springConfiguredAndAutoProxyUsedTogether() {
27-
// instantiation is sufficient to trigger failure if this is going to fail...
2831
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml");
2932
}
3033

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java

+8-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -154,7 +154,7 @@ public SpringPersistenceUnitInfo[] readPersistenceUnitInfos(String[] persistence
154154
/**
155155
* Validate the given stream and return a valid DOM document for parsing.
156156
*/
157-
protected Document buildDocument(ErrorHandler handler, InputStream stream)
157+
Document buildDocument(ErrorHandler handler, InputStream stream)
158158
throws ParserConfigurationException, SAXException, IOException {
159159

160160
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -168,9 +168,7 @@ protected Document buildDocument(ErrorHandler handler, InputStream stream)
168168
/**
169169
* Parse the validated document and add entries to the given unit info list.
170170
*/
171-
protected List<SpringPersistenceUnitInfo> parseDocument(
172-
Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
173-
171+
void parseDocument(Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
174172
Element persistence = document.getDocumentElement();
175173
String version = persistence.getAttribute(PERSISTENCE_VERSION);
176174
URL rootUrl = determinePersistenceUnitRootUrl(resource);
@@ -179,14 +177,12 @@ protected List<SpringPersistenceUnitInfo> parseDocument(
179177
for (Element unit : units) {
180178
infos.add(parsePersistenceUnitInfo(unit, version, rootUrl));
181179
}
182-
183-
return infos;
184180
}
185181

186182
/**
187183
* Parse the unit info DOM element.
188184
*/
189-
protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(
185+
SpringPersistenceUnitInfo parsePersistenceUnitInfo(
190186
Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException {
191187

192188
SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo();
@@ -253,7 +249,7 @@ protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(
253249
/**
254250
* Parse the {@code property} XML elements.
255251
*/
256-
protected void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
252+
void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
257253
Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES);
258254
if (propRoot == null) {
259255
return;
@@ -269,7 +265,7 @@ protected void parseProperties(Element persistenceUnit, SpringPersistenceUnitInf
269265
/**
270266
* Parse the {@code class} XML elements.
271267
*/
272-
protected void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
268+
void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
273269
List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME);
274270
for (Element element : classes) {
275271
String value = DomUtils.getTextValue(element).trim();
@@ -282,7 +278,7 @@ protected void parseManagedClasses(Element persistenceUnit, SpringPersistenceUni
282278
/**
283279
* Parse the {@code mapping-file} XML elements.
284280
*/
285-
protected void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
281+
void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
286282
List<Element> files = DomUtils.getChildElementsByTagName(persistenceUnit, MAPPING_FILE_NAME);
287283
for (Element element : files) {
288284
String value = DomUtils.getTextValue(element).trim();
@@ -295,7 +291,7 @@ protected void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitI
295291
/**
296292
* Parse the {@code jar-file} XML elements.
297293
*/
298-
protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
294+
void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
299295
List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL);
300296
for (Element element : jars) {
301297
String value = DomUtils.getTextValue(element).trim();

spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java

+37-10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import java.util.Date;
3838
import java.util.Map;
3939
import java.util.UUID;
40+
import java.util.concurrent.locks.Lock;
41+
import java.util.concurrent.locks.ReentrantLock;
4042

4143
import javax.xml.XMLConstants;
4244
import javax.xml.datatype.Duration;
@@ -192,7 +194,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
192194
@Nullable
193195
private ClassLoader beanClassLoader;
194196

195-
private final Object jaxbContextMonitor = new Object();
197+
private final Lock jaxbContextLock = new ReentrantLock();
196198

197199
@Nullable
198200
private volatile JAXBContext jaxbContext;
@@ -204,6 +206,12 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
204206

205207
private boolean processExternalEntities = false;
206208

209+
@Nullable
210+
private volatile SAXParserFactory schemaParserFactory;
211+
212+
@Nullable
213+
private volatile SAXParserFactory sourceParserFactory;
214+
207215

208216
/**
209217
* Set multiple JAXB context paths. The given array of context paths gets
@@ -426,6 +434,7 @@ public void setMappedClass(Class<?> mappedClass) {
426434
*/
427435
public void setSupportDtd(boolean supportDtd) {
428436
this.supportDtd = supportDtd;
437+
this.sourceParserFactory = null;
429438
}
430439

431440
/**
@@ -450,6 +459,7 @@ public void setProcessExternalEntities(boolean processExternalEntities) {
450459
if (processExternalEntities) {
451460
this.supportDtd = true;
452461
}
462+
this.sourceParserFactory = null;
453463
}
454464

455465
/**
@@ -497,7 +507,9 @@ public JAXBContext getJaxbContext() {
497507
if (context != null) {
498508
return context;
499509
}
500-
synchronized (this.jaxbContextMonitor) {
510+
511+
this.jaxbContextLock.lock();
512+
try {
501513
context = this.jaxbContext;
502514
if (context == null) {
503515
try {
@@ -521,6 +533,9 @@ else if (!ObjectUtils.isEmpty(this.packagesToScan)) {
521533
}
522534
return context;
523535
}
536+
finally {
537+
this.jaxbContextLock.unlock();
538+
}
524539
}
525540

526541
private JAXBContext createJaxbContextFromContextPath(String contextPath) throws JAXBException {
@@ -587,17 +602,24 @@ private Schema loadSchema(Resource[] resources, String schemaLanguage) throws IO
587602
Assert.notEmpty(resources, "No resources given");
588603
Assert.hasLength(schemaLanguage, "No schema language provided");
589604
Source[] schemaSources = new Source[resources.length];
590-
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
591-
saxParserFactory.setNamespaceAware(true);
592-
saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
605+
606+
SAXParserFactory saxParserFactory = this.schemaParserFactory;
607+
if (saxParserFactory == null) {
608+
saxParserFactory = SAXParserFactory.newInstance();
609+
saxParserFactory.setNamespaceAware(true);
610+
saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
611+
this.schemaParserFactory = saxParserFactory;
612+
}
593613
SAXParser saxParser = saxParserFactory.newSAXParser();
594614
XMLReader xmlReader = saxParser.getXMLReader();
615+
595616
for (int i = 0; i < resources.length; i++) {
596617
Resource resource = resources[i];
597618
Assert.isTrue(resource != null && resource.exists(), () -> "Resource does not exist: " + resource);
598619
InputSource inputSource = SaxResourceUtils.createInputSource(resource);
599620
schemaSources[i] = new SAXSource(xmlReader, inputSource);
600621
}
622+
601623
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
602624
if (this.schemaResourceResolver != null) {
603625
schemaFactory.setResourceResolver(this.schemaResourceResolver);
@@ -886,11 +908,16 @@ else if (streamSource.getReader() != null) {
886908

887909
try {
888910
if (xmlReader == null) {
889-
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
890-
saxParserFactory.setNamespaceAware(true);
891-
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
892-
String name = "http://xml.org/sax/features/external-general-entities";
893-
saxParserFactory.setFeature(name, isProcessExternalEntities());
911+
SAXParserFactory saxParserFactory = this.sourceParserFactory;
912+
if (saxParserFactory == null) {
913+
saxParserFactory = SAXParserFactory.newInstance();
914+
saxParserFactory.setNamespaceAware(true);
915+
saxParserFactory.setFeature(
916+
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
917+
saxParserFactory.setFeature(
918+
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
919+
this.sourceParserFactory = saxParserFactory;
920+
}
894921
SAXParser saxParser = saxParserFactory.newSAXParser();
895922
xmlReader = saxParser.getXMLReader();
896923
}

spring-oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java

+28-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -83,9 +83,10 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
8383
private boolean processExternalEntities = false;
8484

8585
@Nullable
86-
private DocumentBuilderFactory documentBuilderFactory;
86+
private volatile DocumentBuilderFactory documentBuilderFactory;
8787

88-
private final Object documentBuilderFactoryMonitor = new Object();
88+
@Nullable
89+
private volatile SAXParserFactory saxParserFactory;
8990

9091

9192
/**
@@ -94,6 +95,8 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
9495
*/
9596
public void setSupportDtd(boolean supportDtd) {
9697
this.supportDtd = supportDtd;
98+
this.documentBuilderFactory = null;
99+
this.saxParserFactory = null;
97100
}
98101

99102
/**
@@ -118,6 +121,8 @@ public void setProcessExternalEntities(boolean processExternalEntities) {
118121
if (processExternalEntities) {
119122
this.supportDtd = true;
120123
}
124+
this.documentBuilderFactory = null;
125+
this.saxParserFactory = null;
121126
}
122127

123128
/**
@@ -137,14 +142,13 @@ public boolean isProcessExternalEntities() {
137142
*/
138143
protected Document buildDocument() {
139144
try {
140-
DocumentBuilder documentBuilder;
141-
synchronized (this.documentBuilderFactoryMonitor) {
142-
if (this.documentBuilderFactory == null) {
143-
this.documentBuilderFactory = createDocumentBuilderFactory();
144-
}
145-
documentBuilder = createDocumentBuilder(this.documentBuilderFactory);
145+
DocumentBuilderFactory builderFactory = this.documentBuilderFactory;
146+
if (builderFactory == null) {
147+
builderFactory = createDocumentBuilderFactory();
148+
this.documentBuilderFactory = builderFactory;
146149
}
147-
return documentBuilder.newDocument();
150+
DocumentBuilder builder = createDocumentBuilder(builderFactory);
151+
return builder.newDocument();
148152
}
149153
catch (ParserConfigurationException ex) {
150154
throw new UnmarshallingFailureException("Could not create document placeholder: " + ex.getMessage(), ex);
@@ -179,11 +183,11 @@ protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserCon
179183
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
180184
throws ParserConfigurationException {
181185

182-
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
186+
DocumentBuilder builder = factory.newDocumentBuilder();
183187
if (!isProcessExternalEntities()) {
184-
documentBuilder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
188+
builder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
185189
}
186-
return documentBuilder;
190+
return builder;
187191
}
188192

189193
/**
@@ -193,11 +197,17 @@ protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
193197
* @throws ParserConfigurationException if thrown by JAXP methods
194198
*/
195199
protected XMLReader createXmlReader() throws SAXException, ParserConfigurationException {
196-
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
197-
saxParserFactory.setNamespaceAware(true);
198-
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
199-
saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
200-
SAXParser saxParser = saxParserFactory.newSAXParser();
200+
SAXParserFactory parserFactory = this.saxParserFactory;
201+
if (parserFactory == null) {
202+
parserFactory = SAXParserFactory.newInstance();
203+
parserFactory.setNamespaceAware(true);
204+
parserFactory.setFeature(
205+
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
206+
parserFactory.setFeature(
207+
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
208+
this.saxParserFactory = parserFactory;
209+
}
210+
SAXParser saxParser = parserFactory.newSAXParser();
201211
XMLReader xmlReader = saxParser.getXMLReader();
202212
if (!isProcessExternalEntities()) {
203213
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);

spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,6 +61,7 @@
6161
* @author Arjen Poutsma
6262
* @author Sebastien Deleuze
6363
* @author Rossen Stoyanchev
64+
* @author Juergen Hoeller
6465
* @since 3.0
6566
* @see MarshallingHttpMessageConverter
6667
*/
@@ -70,13 +71,17 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
7071

7172
private boolean processExternalEntities = false;
7273

74+
@Nullable
75+
private volatile SAXParserFactory sourceParserFactory;
76+
7377

7478
/**
7579
* Indicate whether DTD parsing should be supported.
7680
* <p>Default is {@code false} meaning that DTD is disabled.
7781
*/
7882
public void setSupportDtd(boolean supportDtd) {
7983
this.supportDtd = supportDtd;
84+
this.sourceParserFactory = null;
8085
}
8186

8287
/**
@@ -97,6 +102,7 @@ public void setProcessExternalEntities(boolean processExternalEntities) {
97102
if (processExternalEntities) {
98103
this.supportDtd = true;
99104
}
105+
this.sourceParserFactory = null;
100106
}
101107

102108
/**
@@ -156,11 +162,16 @@ protected Source processSource(Source source) {
156162
if (source instanceof StreamSource streamSource) {
157163
InputSource inputSource = new InputSource(streamSource.getInputStream());
158164
try {
159-
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
160-
saxParserFactory.setNamespaceAware(true);
161-
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
162-
String featureName = "http://xml.org/sax/features/external-general-entities";
163-
saxParserFactory.setFeature(featureName, isProcessExternalEntities());
165+
SAXParserFactory saxParserFactory = this.sourceParserFactory;
166+
if (saxParserFactory == null) {
167+
saxParserFactory = SAXParserFactory.newInstance();
168+
saxParserFactory.setNamespaceAware(true);
169+
saxParserFactory.setFeature(
170+
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
171+
saxParserFactory.setFeature(
172+
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
173+
this.sourceParserFactory = saxParserFactory;
174+
}
164175
SAXParser saxParser = saxParserFactory.newSAXParser();
165176
XMLReader xmlReader = saxParser.getXMLReader();
166177
if (!isProcessExternalEntities()) {

0 commit comments

Comments
 (0)