Skip to content

Commit 057fd46

Browse files
authored
added jaxb-jakarta module on the basis of jaxb module (#2014)
1 parent 865c914 commit 057fd46

18 files changed

+1429
-0
lines changed

jaxb-jakarta/pom.xml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2012-2023 The Feign Authors
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7+
in compliance with the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software distributed under the License
12+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13+
or implied. See the License for the specific language governing permissions and limitations under
14+
the License.
15+
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<modelVersion>4.0.0</modelVersion>
21+
22+
<parent>
23+
<groupId>io.github.openfeign</groupId>
24+
<artifactId>parent</artifactId>
25+
<version>12.4-SNAPSHOT</version>
26+
</parent>
27+
28+
<artifactId>feign-jaxb-jakarta</artifactId>
29+
<name>Feign JAXB Jakarta</name>
30+
<description>Feign JAXB Jakarta</description>
31+
32+
<properties>
33+
<main.basedir>${project.basedir}/..</main.basedir>
34+
</properties>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>${project.groupId}</groupId>
39+
<artifactId>feign-core</artifactId>
40+
</dependency>
41+
42+
<dependency>
43+
<groupId>${project.groupId}</groupId>
44+
<artifactId>feign-core</artifactId>
45+
<type>test-jar</type>
46+
<scope>test</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>jakarta.xml.bind</groupId>
50+
<artifactId>jakarta.xml.bind-api</artifactId>
51+
<version>4.0.0</version>
52+
</dependency>
53+
54+
<!-- Test -->
55+
<dependency>
56+
<groupId>com.sun.xml.bind</groupId>
57+
<artifactId>jaxb-impl</artifactId>
58+
<version>4.0.0</version>
59+
<scope>test</scope>
60+
</dependency>
61+
</dependencies>
62+
63+
</project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.jaxb;
15+
16+
/**
17+
* Encapsulate data used to build the cache key of JAXBContext.
18+
*/
19+
interface JAXBContextCacheKey {
20+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.jaxb;
15+
16+
import java.util.Objects;
17+
18+
/**
19+
* Encapsulate data used to build the cache key of JAXBContext when created using class mode.
20+
*/
21+
final class JAXBContextClassCacheKey implements JAXBContextCacheKey {
22+
23+
private final Class<?> clazz;
24+
25+
JAXBContextClassCacheKey(Class<?> clazz) {
26+
this.clazz = clazz;
27+
}
28+
29+
@Override
30+
public boolean equals(Object o) {
31+
if (this == o)
32+
return true;
33+
if (o == null || getClass() != o.getClass())
34+
return false;
35+
JAXBContextClassCacheKey that = (JAXBContextClassCacheKey) o;
36+
return clazz.equals(that.clazz);
37+
}
38+
39+
@Override
40+
public int hashCode() {
41+
return Objects.hash(clazz);
42+
}
43+
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.jaxb;
15+
16+
import jakarta.xml.bind.*;
17+
import java.util.HashMap;
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.Map.Entry;
21+
import java.util.concurrent.ConcurrentHashMap;
22+
23+
/**
24+
* Creates and caches JAXB contexts as well as creates Marshallers and Unmarshallers for each
25+
* context. Since JAXB contexts creation can be an expensive task, JAXB context can be preloaded on
26+
* factory creation otherwise they will be created and cached dynamically when needed.
27+
*/
28+
public final class JAXBContextFactory {
29+
30+
private final ConcurrentHashMap<JAXBContextCacheKey, JAXBContext> jaxbContexts =
31+
new ConcurrentHashMap<>(64);
32+
private final Map<String, Object> properties;
33+
private final JAXBContextInstantationMode jaxbContextInstantationMode;
34+
35+
private JAXBContextFactory(Map<String, Object> properties,
36+
JAXBContextInstantationMode jaxbContextInstantationMode) {
37+
this.properties = properties;
38+
this.jaxbContextInstantationMode = jaxbContextInstantationMode;
39+
}
40+
41+
/**
42+
* Creates a new {@link jakarta.xml.bind.Unmarshaller} that handles the supplied class.
43+
*/
44+
public Unmarshaller createUnmarshaller(Class<?> clazz) throws JAXBException {
45+
return getContext(clazz).createUnmarshaller();
46+
}
47+
48+
/**
49+
* Creates a new {@link jakarta.xml.bind.Marshaller} that handles the supplied class.
50+
*/
51+
public Marshaller createMarshaller(Class<?> clazz) throws JAXBException {
52+
Marshaller marshaller = getContext(clazz).createMarshaller();
53+
setMarshallerProperties(marshaller);
54+
return marshaller;
55+
}
56+
57+
private void setMarshallerProperties(Marshaller marshaller) throws PropertyException {
58+
for (Entry<String, Object> en : properties.entrySet()) {
59+
marshaller.setProperty(en.getKey(), en.getValue());
60+
}
61+
}
62+
63+
private JAXBContext getContext(Class<?> clazz) throws JAXBException {
64+
JAXBContextCacheKey cacheKey = jaxbContextInstantationMode.getJAXBContextCacheKey(clazz);
65+
JAXBContext jaxbContext = this.jaxbContexts.get(cacheKey);
66+
67+
if (jaxbContext == null) {
68+
jaxbContext = jaxbContextInstantationMode.getJAXBContext(clazz);
69+
this.jaxbContexts.putIfAbsent(cacheKey, jaxbContext);
70+
}
71+
return jaxbContext;
72+
}
73+
74+
/**
75+
* Will preload factory's cache with JAXBContext for provided classes
76+
*
77+
* @param classes
78+
* @throws jakarta.xml.bind.JAXBException
79+
*/
80+
private void preloadContextCache(List<Class<?>> classes) throws JAXBException {
81+
if (classes != null && !classes.isEmpty()) {
82+
for (Class<?> clazz : classes) {
83+
getContext(clazz);
84+
}
85+
}
86+
}
87+
88+
/**
89+
* Creates instances of {@link JAXBContextFactory}.
90+
*/
91+
public static class Builder {
92+
93+
private final Map<String, Object> properties = new HashMap<>(10);
94+
95+
private JAXBContextInstantationMode jaxbContextInstantationMode =
96+
JAXBContextInstantationMode.CLASS;
97+
98+
/**
99+
* Sets the jaxb.encoding property of any Marshaller created by this factory.
100+
*/
101+
public Builder withMarshallerJAXBEncoding(String value) {
102+
properties.put(Marshaller.JAXB_ENCODING, value);
103+
return this;
104+
}
105+
106+
/**
107+
* Sets the jaxb.schemaLocation property of any Marshaller created by this factory.
108+
*/
109+
public Builder withMarshallerSchemaLocation(String value) {
110+
properties.put(Marshaller.JAXB_SCHEMA_LOCATION, value);
111+
return this;
112+
}
113+
114+
/**
115+
* Sets the jaxb.noNamespaceSchemaLocation property of any Marshaller created by this factory.
116+
*/
117+
public Builder withMarshallerNoNamespaceSchemaLocation(String value) {
118+
properties.put(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, value);
119+
return this;
120+
}
121+
122+
/**
123+
* Sets the jaxb.formatted.output property of any Marshaller created by this factory.
124+
*/
125+
public Builder withMarshallerFormattedOutput(Boolean value) {
126+
properties.put(Marshaller.JAXB_FORMATTED_OUTPUT, value);
127+
return this;
128+
}
129+
130+
/**
131+
* Sets the jaxb.fragment property of any Marshaller created by this factory.
132+
*/
133+
public Builder withMarshallerFragment(Boolean value) {
134+
properties.put(Marshaller.JAXB_FRAGMENT, value);
135+
return this;
136+
}
137+
138+
/**
139+
* Sets the given property of any Marshaller created by this factory.
140+
*
141+
* <p>
142+
* Example : <br>
143+
* <br>
144+
* <code>
145+
* new JAXBContextFactory.Builder()
146+
* .withProperty("com.sun.xml.internal.bind.xmlHeaders", "&lt;!DOCTYPE Example SYSTEM \&quot;example.dtd\&quot;&gt;")
147+
* .build();
148+
* </code>
149+
* </p>
150+
*/
151+
public Builder withProperty(String key, Object value) {
152+
properties.put(key, value);
153+
return this;
154+
}
155+
156+
/**
157+
* Provide an instantiation mode for JAXB Contexts, can be class or package, default is class if
158+
* this method is not called.
159+
*
160+
* <p>
161+
* Example : <br>
162+
* <br>
163+
* <code>
164+
* new JAXBContextFactory.Builder()
165+
* .withJAXBContextInstantiationMode(JAXBContextInstantationMode.PACKAGE)
166+
* .build();
167+
* </code>
168+
* </p>
169+
*/
170+
public Builder withJAXBContextInstantiationMode(JAXBContextInstantationMode jaxbContextInstantiationMode) {
171+
this.jaxbContextInstantationMode = jaxbContextInstantiationMode;
172+
return this;
173+
}
174+
175+
/**
176+
* Creates a new {@link JAXBContextFactory} instance with a lazy loading cached context
177+
*/
178+
public JAXBContextFactory build() {
179+
return new JAXBContextFactory(properties, jaxbContextInstantationMode);
180+
}
181+
182+
/**
183+
* Creates a new {@link JAXBContextFactory} instance. Pre-loads context cache with given classes
184+
*
185+
* @param classes
186+
* @return ContextFactory with a pre-populated JAXBContext cache
187+
* @throws jakarta.xml.bind.JAXBException if provided classes can't be used for JAXBContext
188+
* generation most likely due to missing JAXB annotations
189+
*/
190+
public JAXBContextFactory build(List<Class<?>> classes) throws JAXBException {
191+
JAXBContextFactory factory = new JAXBContextFactory(properties, jaxbContextInstantationMode);
192+
factory.preloadContextCache(classes);
193+
return factory;
194+
}
195+
}
196+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.jaxb;
15+
16+
17+
import jakarta.xml.bind.JAXBContext;
18+
import jakarta.xml.bind.JAXBException;
19+
20+
/**
21+
* Provides differents ways to instantiate a JAXB Context.
22+
*/
23+
public enum JAXBContextInstantationMode {
24+
25+
CLASS {
26+
@Override
27+
JAXBContextCacheKey getJAXBContextCacheKey(Class<?> clazz) {
28+
return new JAXBContextClassCacheKey(clazz);
29+
}
30+
31+
@Override
32+
JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
33+
return JAXBContext.newInstance(clazz);
34+
}
35+
},
36+
37+
PACKAGE {
38+
@Override
39+
JAXBContextCacheKey getJAXBContextCacheKey(Class<?> clazz) {
40+
return new JAXBContextPackageCacheKey(clazz.getPackage().getName(), clazz.getClassLoader());
41+
}
42+
43+
@Override
44+
JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
45+
return JAXBContext.newInstance(clazz.getPackage().getName(), clazz.getClassLoader());
46+
}
47+
};
48+
49+
abstract JAXBContextCacheKey getJAXBContextCacheKey(Class<?> clazz);
50+
51+
abstract JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException;
52+
}

0 commit comments

Comments
 (0)