Skip to content

Commit 57884ff

Browse files
blutorangeawa-xima
andauthored
Fix #316, Unable to override JAXBContextFactory through properties (#317)
* Fix #316, Unable to override JAXBContextFactory through properties Remove jakarta.xml.bind.JAXBContextFactory from properties passed to provider, as they are required to throw if they find an unsupported property. This was already done for the other find overload. * remove new test and add test case to existing tests * Update copyright years --------- Co-authored-by: Andre Wachsmuth <[email protected]>
1 parent 3cb177a commit 57884ff

File tree

5 files changed

+84
-41
lines changed

5 files changed

+84
-41
lines changed

api/src/main/java/jakarta/xml/bind/ContextFinder.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2024 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -310,7 +310,7 @@ static JAXBContext find(String factoryId,
310310
}
311311
}
312312
if (factoryName != null) {
313-
return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
313+
return newInstance(contextPath, contextPathClasses, factoryName, classLoader, cleanProperties(properties));
314314
}
315315
}
316316

@@ -354,14 +354,7 @@ static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JA
354354
}
355355
}
356356
if (factoryClassName != null) {
357-
//Providers are not required to understand JAXB_CONTEXT_FACTORY property
358-
//and they must throw a JAXBException if they see it, so we need to remove it
359-
//from properties passed to them
360-
Map<String, ?> props = properties.entrySet()
361-
.stream()
362-
.filter(Predicate.not(e -> JAXBContext.JAXB_CONTEXT_FACTORY.equals(e.getKey())))
363-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
364-
return newInstance(classes, props, factoryClassName);
357+
return newInstance(classes, cleanProperties(properties), factoryClassName);
365358
}
366359
}
367360

@@ -396,6 +389,16 @@ private static String classNameFromSystemProperties() throws JAXBException {
396389
return null;
397390
}
398391

392+
private static Map<String, ?> cleanProperties(Map<String, ?> properties) {
393+
// Providers are not required to understand JAXB_CONTEXT_FACTORY property,
394+
// and they must throw a JAXBException if they see it, so we need to remove it
395+
// from properties passed to them
396+
return properties.entrySet()
397+
.stream()
398+
.filter(Predicate.not(e -> JAXBContext.JAXB_CONTEXT_FACTORY.equals(e.getKey())))
399+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
400+
}
401+
399402
private static String getSystemProperty(String property) {
400403
logger.log(Level.FINE, "Checking system property {0}", property);
401404
String value = AccessController.doPrivileged(new GetPropertyAction(property));

jaxb-api-test/src/test/java/jakarta/xml/bind/test/JAXBContextTest.java

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -25,6 +25,7 @@
2525
import java.nio.file.StandardOpenOption;
2626
import java.util.Arrays;
2727
import java.util.Collection;
28+
import java.util.Map;
2829
import java.util.logging.Logger;
2930

3031
import static junit.framework.TestCase.assertTrue;
@@ -73,6 +74,9 @@ public class JAXBContextTest {
7374
// scenario name - just for logging
7475
String scenario;
7576

77+
// properties to pass to JAXBContext#newContext
78+
private Map<String, ?> properties;
79+
7680
// java policy file for testing w/security manager
7781
private String expectedFactory;
7882
private Class<?> expectedException;
@@ -83,70 +87,74 @@ public static Collection configurations() {
8387
return Arrays.asList(new Object[][]{
8488
// scenario-name, jaxb.properties, svc, arg1, arg2, system-props
8589
// {"scenario-1", FACTORY_ID_LEGACY + "="+PACKAGE_LEGACY+"Valid", null, PACKAGE_LEGACY+"Valid$JAXBContext1", null, null},
86-
{"scenario-3", FACTORY_ID_LEGACY + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null},
87-
{"scenario-4", FACTORY_ID_LEGACY + "="+PACKAGE_LEGACY+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null},
90+
{"scenario-3", FACTORY_ID_LEGACY + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null, null},
91+
{"scenario-4", FACTORY_ID_LEGACY + "="+PACKAGE_LEGACY+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null, null},
8892
// {"scenario-13", FACTORY_ID_LEGACY + "="+PACKAGE_LEGACY+"Valid", PACKAGE_LEGACY+"Valid2", PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid3"},
8993

9094
// {"scenario-1", FACTORY_ID_LEGACY + "="+PACKAGE_SPI+"Valid", null, PACKAGE_SPI+"Valid$JAXBContext1", null, null},
91-
{"scenario-3", FACTORY_ID_LEGACY + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null},
92-
{"scenario-4", FACTORY_ID_LEGACY + "="+PACKAGE_SPI+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null},
95+
{"scenario-3", FACTORY_ID_LEGACY + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null, null},
96+
{"scenario-4", FACTORY_ID_LEGACY + "="+PACKAGE_SPI+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null, null},
9397
// {"scenario-13", FACTORY_ID_LEGACY + "="+PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid2", PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid3"},
9498

9599
// {"scenario-1", FACTORY_ID + "="+PACKAGE_SPI+"Valid", null, PACKAGE_SPI+"Valid$JAXBContext1", null, null},
96-
{"scenario-3", FACTORY_ID + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null},
97-
{"scenario-4", FACTORY_ID + "="+PACKAGE_SPI+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null},
100+
{"scenario-3", FACTORY_ID + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null, null},
101+
{"scenario-4", FACTORY_ID + "="+PACKAGE_SPI+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null, null},
98102
// {"scenario-13", FACTORY_ID + "="+PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid2", PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid3"},
99103

100104
// {"scenario-1", FACTORY_ID + "="+PACKAGE_LEGACY+"Valid", null, PACKAGE_LEGACY+"Valid$JAXBContext1", null, null},
101-
{"scenario-3", FACTORY_ID + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null},
102-
{"scenario-4", FACTORY_ID + "="+PACKAGE_LEGACY+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null},
105+
{"scenario-3", FACTORY_ID + "=non.existing.FactoryClass", null, null, jakarta.xml.bind.JAXBException.class, null, null},
106+
{"scenario-4", FACTORY_ID + "="+PACKAGE_LEGACY+"Invalid", null, null, jakarta.xml.bind.JAXBException.class, null, null},
103107
// {"scenario-13", FACTORY_ID + "="+PACKAGE_LEGACY+"Valid", PACKAGE_LEGACY+"Valid2", PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid3"},
104108

105109

106-
{"scenario-2", "something=AnotherThing", null, null, jakarta.xml.bind.JAXBException.class, null},
110+
{"scenario-2", "something=AnotherThing", null, null, jakarta.xml.bind.JAXBException.class, null, null},
107111

108112
// service loader
109-
{"scenario-8", null, PACKAGE_SPI+"Valid\n", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
110-
{"scenario-9", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
111-
{"scenario-11", null, PACKAGE_SPI+"Invalid", null, jakarta.xml.bind.JAXBException.class, null},
112-
{"scenario-15", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
113+
{"scenario-8", null, PACKAGE_SPI+"Valid\n", PACKAGE_SPI+"Valid$JAXBContext1", null, null, null},
114+
{"scenario-9", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null, null},
115+
{"scenario-11", null, PACKAGE_SPI+"Invalid", null, jakarta.xml.bind.JAXBException.class, null, null},
116+
{"scenario-15", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null, null},
113117

114118
// service loader - legacy
115119
// {"scenario-8 legacy-svc", null, PACKAGE_SPI+"Valid\n", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
116120
// {"scenario-9 legacy-svc", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
117-
{"scenario-11 legacy-svc", null, PACKAGE_SPI+"Invalid", null, jakarta.xml.bind.JAXBException.class, null},
121+
{"scenario-11 legacy-svc", null, PACKAGE_SPI+"Invalid", null, jakarta.xml.bind.JAXBException.class, null, null},
118122
// {"scenario-15 legacy-svc", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null},
119123

120124
// service loader - legacy
121125
// {"scenario-8 legacy-svc", null, PACKAGE_LEGACY+"Valid\n", PACKAGE_LEGACY+"Valid$JAXBContext1", null, null},
122126
// {"scenario-9 legacy-svc", null, PACKAGE_LEGACY+"Valid", PACKAGE_LEGACY+"Valid$JAXBContext1", null, null},
123-
{"scenario-11 legacy-svc", null, PACKAGE_LEGACY+"Invalid", null, jakarta.xml.bind.JAXBException.class, null},
127+
{"scenario-11 legacy-svc", null, PACKAGE_LEGACY+"Invalid", null, jakarta.xml.bind.JAXBException.class, null, null},
124128
// {"scenario-15 legacy-svc", null, PACKAGE_LEGACY+"Valid", PACKAGE_LEGACY+"Valid$JAXBContext1", null, null},
125129

126130
// system property
127-
{"scenario-5", null, null, PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid"},
128-
{"scenario-7", null, null, null, jakarta.xml.bind.JAXBException.class, PACKAGE_SPI+"Invalid"},
129-
{"scenario-14", null, PACKAGE_SPI+"Valid2", PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid"},
131+
{"scenario-5", null, null, PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid", null},
132+
{"scenario-7", null, null, null, jakarta.xml.bind.JAXBException.class, PACKAGE_SPI+"Invalid", null},
133+
{"scenario-14", null, PACKAGE_SPI+"Valid2", PACKAGE_SPI+"Valid$JAXBContext1", null, PACKAGE_SPI+"Valid", null},
134+
135+
{"scenario-5", null, null, PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid", null},
136+
{"scenario-7", null, null, null, jakarta.xml.bind.JAXBException.class, PACKAGE_LEGACY+"Invalid", null},
137+
{"scenario-14", null, PACKAGE_LEGACY+"Valid2", PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid", null},
138+
{"scenario-6", null, null, null, jakarta.xml.bind.JAXBException.class, "jaxb.factory.NonExisting", null},
130139

131-
{"scenario-5", null, null, PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid"},
132-
{"scenario-7", null, null, null, jakarta.xml.bind.JAXBException.class, PACKAGE_LEGACY+"Invalid"},
133-
{"scenario-14", null, PACKAGE_LEGACY+"Valid2", PACKAGE_LEGACY+"Valid$JAXBContext1", null, PACKAGE_LEGACY+"Valid"},
134-
{"scenario-6", null, null, null, jakarta.xml.bind.JAXBException.class, "jaxb.factory.NonExisting"},
140+
{"scenario-10", null, "jaxb.factory.NonExisting", null, jakarta.xml.bind.JAXBException.class, null, null},
135141

136-
{"scenario-10", null, "jaxb.factory.NonExisting", null, jakarta.xml.bind.JAXBException.class, null},
142+
{"scenario-12", null, null, DEFAULT, jakarta.xml.bind.JAXBException.class, null, null},
137143

138-
{"scenario-12", null, null, DEFAULT, jakarta.xml.bind.JAXBException.class, null},
144+
// properties
145+
{"scenario-17", null, PACKAGE_SPI+"Valid", PACKAGE_SPI+"Valid$JAXBContext1", null, null, Map.of("jakarta.xml.bind.JAXBContextFactory", PACKAGE_SPI+"Valid")},
139146
});
140147
}
141148

142-
// scenario-name, jaxb.properties, svc, arg1, arg2, system-props
149+
// scenario-name, jaxb.properties, svc, arg1, arg2, system-props, properties
143150
public JAXBContextTest(
144151
String scenario,
145152
String jaxbPropertiesClass,
146153
String spiClass,
147154
String expectedFactory,
148155
Class<?> expectedException,
149-
String systemProperty
156+
String systemProperty,
157+
Map<String, ?> properties
150158
) {
151159

152160
// ensure setup may be done ...
@@ -161,6 +169,7 @@ public JAXBContextTest(
161169
this.scenario = scenario;
162170
this.expectedFactory = expectedFactory;
163171
this.expectedException = expectedException;
172+
this.properties = properties;
164173

165174
if (skipUnsafe && scenario.startsWith("unsafe")) {
166175
log("Skipping unsafe scenario:" + scenario);
@@ -187,7 +196,20 @@ public void testPath() throws IOException {
187196
public void testClasses() throws IOException {
188197
logConfigurations();
189198
try {
190-
JAXBContext ctx = JAXBContext.newInstance(new Class[] {A.class}, null);
199+
JAXBContext ctx = JAXBContext.newInstance(new Class<?>[] {A.class}, properties);
200+
handleResult(ctx);
201+
} catch (Throwable throwable) {
202+
handleThrowable(throwable);
203+
} finally {
204+
doFinally();
205+
}
206+
}
207+
208+
@Test
209+
public void testClassLoader() throws IOException {
210+
logConfigurations();
211+
try {
212+
JAXBContext ctx = JAXBContext.newInstance(A.class.getName(), JAXBContextTest.class.getClassLoader(), properties);
191213
handleResult(ctx);
192214
} catch (Throwable throwable) {
193215
handleThrowable(throwable);

jaxb-api-test/src/test/java/jaxb/factory/spi/Valid.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -24,11 +24,17 @@ public class Valid implements JAXBContextFactory {
2424

2525
@Override
2626
public JAXBContext createContext(Class<?>[] classesToBeBound, Map<String, ?> properties) throws JAXBException {
27+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
28+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
29+
}
2730
return new JAXBContext1();
2831
}
2932

3033
@Override
3134
public JAXBContext createContext(String contextPath, ClassLoader classLoader, Map<String, ?> properties) throws JAXBException {
35+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
36+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
37+
}
3238
return new JAXBContext1();
3339
}
3440

jaxb-api-test/src/test/java/jaxb/factory/spi/Valid2.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -24,11 +24,17 @@ public class Valid2 implements JAXBContextFactory {
2424

2525
@Override
2626
public JAXBContext createContext(Class<?>[] classesToBeBound, Map<String, ?> properties) throws JAXBException {
27+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
28+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
29+
}
2730
return new JAXBContext1();
2831
}
2932

3033
@Override
3134
public JAXBContext createContext(String contextPath, ClassLoader classLoader, Map<String, ?> properties) throws JAXBException {
35+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
36+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
37+
}
3238
return new JAXBContext1();
3339
}
3440

jaxb-api-test/src/test/java/jaxb/factory/spi/Valid3.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -24,11 +24,17 @@ public class Valid3 implements JAXBContextFactory {
2424

2525
@Override
2626
public JAXBContext createContext(Class<?>[] classesToBeBound, Map<String, ?> properties) throws JAXBException {
27+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
28+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
29+
}
2730
return new JAXBContext1();
2831
}
2932

3033
@Override
3134
public JAXBContext createContext(String contextPath, ClassLoader classLoader, Map<String, ?> properties) throws JAXBException {
35+
if (properties != null && properties.containsKey("jakarta.xml.bind.JAXBContextFactory")) {
36+
throw new JAXBException("property \"jakarta.xml.bind.JAXBContextFactory\" is not supported");
37+
}
3238
return new JAXBContext1();
3339
}
3440

0 commit comments

Comments
 (0)