Skip to content

Commit 27370d3

Browse files
gunnarmorlinggsmet
authored andcommitted
HV-1280 Setting context class loader to HV's defining CL before calling into JAXB/JAXP;
This makes sure we don't get in touch with a JAXP implementation provided as part of the deployed application when running on WF.
1 parent a8db9cd commit 27370d3

File tree

4 files changed

+184
-9
lines changed

4 files changed

+184
-9
lines changed

engine/src/main/java/org/hibernate/validator/internal/xml/ValidationXmlParser.java

+5
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ public final BootstrapConfiguration parseValidationXml() {
6969
return BootstrapConfigurationImpl.getDefaultBootstrapConfiguration();
7070
}
7171

72+
ClassLoader previousTccl = Thread.currentThread().getContextClassLoader();
73+
7274
try {
75+
Thread.currentThread().setContextClassLoader( ValidationXmlParser.class.getClassLoader() );
76+
7377
// HV-970 The parser helper is only loaded if there actually is a validation.xml file;
7478
// this avoids accessing javax.xml.stream.* (which does not exist on Android) when not actually
7579
// working with the XML configuration
@@ -83,6 +87,7 @@ public final BootstrapConfiguration parseValidationXml() {
8387
return createBootstrapConfiguration( validationConfig );
8488
}
8589
finally {
90+
Thread.currentThread().setContextClassLoader( previousTccl );
8691
closeStream( inputStream );
8792
}
8893
}

engine/src/main/java/org/hibernate/validator/internal/xml/XmlMappingParser.java

+22-9
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,7 @@ public final void parse(Set<InputStream> mappingStreams) {
137137
in.mark( Integer.MAX_VALUE );
138138
}
139139

140-
XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) );
141-
String schemaVersion = xmlParserHelper.getSchemaVersion( "constraint mapping file", xmlEventReader );
142-
String schemaResourceName = getSchemaResourceName( schemaVersion );
143-
Schema schema = xmlParserHelper.getSchema( schemaResourceName );
144-
145-
Unmarshaller unmarshaller = jc.createUnmarshaller();
146-
unmarshaller.setSchema( schema );
147-
148-
ConstraintMappingsType mapping = getValidationConfig( xmlEventReader, unmarshaller );
140+
ConstraintMappingsType mapping = unmarshal( jc, in );
149141
String defaultPackage = mapping.getDefaultPackage();
150142

151143
parseConstraintDefinitions(
@@ -180,6 +172,27 @@ public final void parse(Set<InputStream> mappingStreams) {
180172
}
181173
}
182174

175+
private ConstraintMappingsType unmarshal(JAXBContext jc, InputStream in) throws JAXBException {
176+
ClassLoader previousTccl = Thread.currentThread().getContextClassLoader();
177+
178+
try {
179+
Thread.currentThread().setContextClassLoader( ValidationXmlParser.class.getClassLoader() );
180+
181+
XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) );
182+
String schemaVersion = xmlParserHelper.getSchemaVersion( "constraint mapping file", xmlEventReader );
183+
String schemaResourceName = getSchemaResourceName( schemaVersion );
184+
Schema schema = xmlParserHelper.getSchema( schemaResourceName );
185+
186+
Unmarshaller unmarshaller = jc.createUnmarshaller();
187+
unmarshaller.setSchema( schema );
188+
189+
return getValidationConfig( xmlEventReader, unmarshaller );
190+
}
191+
finally {
192+
Thread.currentThread().setContextClassLoader( previousTccl );
193+
}
194+
}
195+
183196
public final Set<Class<?>> getXmlConfiguredClasses() {
184197
return processedClasses;
185198
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Hibernate Validator, declare and validate application constraints
3+
*
4+
* License: Apache License, Version 2.0
5+
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6+
*/
7+
package org.hibernate.validator.integration.wildfly.xml;
8+
9+
/**
10+
* @author Gunnar Morling
11+
*/
12+
public class Camera {
13+
14+
public String brand = null;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Hibernate Validator, declare and validate application constraints
3+
*
4+
* License: Apache License, Version 2.0
5+
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6+
*/
7+
package org.hibernate.validator.integration.wildfly.xml;
8+
9+
import static org.junit.Assert.assertEquals;
10+
import static org.junit.Assert.assertSame;
11+
12+
import java.util.Set;
13+
14+
import javax.inject.Inject;
15+
import javax.validation.ConstraintViolation;
16+
import javax.validation.Validator;
17+
import javax.validation.constraints.NotNull;
18+
19+
import org.jboss.arquillian.container.test.api.Deployer;
20+
import org.jboss.arquillian.container.test.api.Deployment;
21+
import org.jboss.arquillian.container.test.api.RunAsClient;
22+
import org.jboss.arquillian.junit.Arquillian;
23+
import org.jboss.arquillian.junit.InSequence;
24+
import org.jboss.arquillian.test.api.ArquillianResource;
25+
import org.jboss.shrinkwrap.api.Archive;
26+
import org.jboss.shrinkwrap.api.ShrinkWrap;
27+
import org.jboss.shrinkwrap.api.asset.Asset;
28+
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
29+
import org.jboss.shrinkwrap.api.asset.StringAsset;
30+
import org.jboss.shrinkwrap.api.spec.WebArchive;
31+
import org.jboss.shrinkwrap.descriptor.api.Descriptors;
32+
import org.jboss.shrinkwrap.descriptor.api.validationConfiguration11.ValidationConfigurationDescriptor;
33+
import org.jboss.shrinkwrap.descriptor.api.validationMapping11.ValidationMappingDescriptor;
34+
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
35+
import org.junit.Test;
36+
import org.junit.runner.RunWith;
37+
38+
/**
39+
* Test for https://hibernate.atlassian.net/browse/HV-1280. To reproduce the issue, the deployment must be done twice
40+
* (it will only show up during the 2nd deploy), which is why the test is managing the deployment itself via client-side
41+
* test methods.
42+
*
43+
* @author Gunnar Morling
44+
*/
45+
@RunWith(Arquillian.class)
46+
public class JaxpContainedInDeploymentIT {
47+
48+
private static final String WAR_FILE_NAME = JaxpContainedInDeploymentIT.class.getSimpleName() + ".war";
49+
50+
@ArquillianResource
51+
private Deployer deployer;
52+
53+
@Inject
54+
private Validator validator;
55+
56+
@Deployment(name = "jaxpit", managed = false)
57+
public static Archive<?> createTestArchive() {
58+
return ShrinkWrap
59+
.create( WebArchive.class, WAR_FILE_NAME )
60+
.addClass( Camera.class )
61+
.addAsResource( validationXml(), "META-INF/validation.xml" )
62+
.addAsResource( mappingXml(), "META-INF/my-mapping.xml" )
63+
.addAsLibrary( Maven.resolver().resolve( "xerces:xercesImpl:2.9.1" ).withoutTransitivity().asSingleFile() )
64+
.addAsResource( "log4j.properties" )
65+
.addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" );
66+
}
67+
68+
private static Asset validationXml() {
69+
String validationXml = Descriptors.create( ValidationConfigurationDescriptor.class )
70+
.version( "1.1" )
71+
.constraintMapping( "META-INF/my-mapping.xml" )
72+
.exportAsString();
73+
return new StringAsset( validationXml );
74+
}
75+
76+
private static Asset mappingXml() {
77+
String mappingXml = Descriptors.create( ValidationMappingDescriptor.class )
78+
.version( "1.1" )
79+
.createBean()
80+
.clazz( Camera.class.getName() )
81+
.createField()
82+
.name( "brand" )
83+
.createConstraint()
84+
.annotation( "javax.validation.constraints.NotNull" )
85+
.up()
86+
.up()
87+
.up()
88+
.exportAsString();
89+
return new StringAsset( mappingXml );
90+
}
91+
92+
@Test
93+
@RunAsClient
94+
@InSequence(0)
95+
public void deploy1() throws Exception {
96+
deployer.deploy( "jaxpit" );
97+
}
98+
99+
@Test
100+
@InSequence(1)
101+
public void test1() throws Exception {
102+
doTest();
103+
}
104+
105+
@Test
106+
@RunAsClient
107+
@InSequence(2)
108+
public void undeploy1() throws Exception {
109+
deployer.undeploy( "jaxpit" );
110+
}
111+
112+
@Test
113+
@RunAsClient
114+
@InSequence(3)
115+
public void deploy2() throws Exception {
116+
deployer.deploy( "jaxpit" );
117+
}
118+
119+
@Test
120+
@InSequence(4)
121+
public void test2() throws Exception {
122+
doTest();
123+
}
124+
125+
@Test
126+
@RunAsClient
127+
@InSequence(5)
128+
public void undeploy2() throws Exception {
129+
deployer.undeploy( "jaxpit" );
130+
}
131+
132+
private void doTest() {
133+
Set<ConstraintViolation<Camera>> violations = validator.validate( new Camera() );
134+
135+
assertEquals( 1, violations.size() );
136+
assertSame( NotNull.class, violations.iterator()
137+
.next()
138+
.getConstraintDescriptor()
139+
.getAnnotation()
140+
.annotationType() );
141+
}
142+
}

0 commit comments

Comments
 (0)