Skip to content

Package: XmlUtil

XmlUtil

nameinstructionbranchcomplexitylinemethod
getContext()
M: 26 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%
lambda$marshal$0(Marshaller, String, Object)
M: 12 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
lambda$unmarshal$1(Unmarshaller, String, Object)
M: 12 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
marshal(Object)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
marshal(Object, Writer)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
marshal(Object, Writer, Map)
M: 72 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 18 C: 0
0%
M: 1 C: 0
0%
marshalJson(Object)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
marshalJson(Object, Writer)
M: 20 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
setContextProvider(JAXBContextProvider)
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
unmarshal(Reader, Class)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
unmarshal(Reader, Class, String)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
unmarshal(Reader, Class, String, Map)
M: 166 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 29 C: 0
0%
M: 1 C: 0
0%
unmarshal(String, Class)
M: 20 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
unmarshal(String, Class, String)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
unmarshalJson(Reader, Class, String)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
unmarshalJson(String, Class)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
unmarshalJson(String, Class, String)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2016, 2022 Eurotech and/or its affiliates and others
3: *
4: * This program and the accompanying materials are made
5: * available under the terms of the Eclipse Public License 2.0
6: * which is available at https://www.eclipse.org/legal/epl-2.0/
7: *
8: * SPDX-License-Identifier: EPL-2.0
9: *
10: * Contributors:
11: * Eurotech - initial API and implementation
12: * Red Hat Inc
13: *******************************************************************************/
14: package org.eclipse.kapua.commons.util.xml;
15:
16: import com.google.common.base.Strings;
17: import org.apache.commons.lang.SystemUtils;
18: import org.checkerframework.checker.nullness.qual.Nullable;
19: import org.eclipse.kapua.KapuaException;
20: import org.eclipse.persistence.jaxb.JAXBContextFactory;
21: import org.eclipse.persistence.jaxb.MarshallerProperties;
22: import org.slf4j.Logger;
23: import org.slf4j.LoggerFactory;
24: import org.xml.sax.InputSource;
25: import org.xml.sax.SAXException;
26: import org.xml.sax.XMLReader;
27: import org.xml.sax.helpers.XMLReaderFactory;
28:
29: import javax.validation.constraints.NotNull;
30: import javax.xml.bind.JAXBContext;
31: import javax.xml.bind.JAXBElement;
32: import javax.xml.bind.JAXBException;
33: import javax.xml.bind.MarshalException;
34: import javax.xml.bind.Marshaller;
35: import javax.xml.bind.PropertyException;
36: import javax.xml.bind.UnmarshalException;
37: import javax.xml.bind.Unmarshaller;
38: import javax.xml.bind.ValidationEvent;
39: import javax.xml.bind.util.ValidationEventCollector;
40: import javax.xml.transform.sax.SAXSource;
41: import java.io.IOException;
42: import java.io.Reader;
43: import java.io.StringReader;
44: import java.io.StringWriter;
45: import java.io.Writer;
46: import java.text.MessageFormat;
47: import java.util.Collections;
48: import java.util.HashMap;
49: import java.util.Map;
50: import java.util.Properties;
51:
52: /**
53: * Xml utilities
54: *
55: * @since 1.0.0
56: */
57: public class XmlUtil {
58:
59: private static final Logger LOG = LoggerFactory.getLogger(XmlUtil.class);
60:
61: /**
62: * Constructor.
63: *
64: * @since 1.0.0
65: */
66: private XmlUtil() {
67: }
68:
69: private static JAXBContextProvider jaxbContextProvider;
70:
71: /**
72: * Sets the {@link JAXBContextProvider} to use.
73: *
74: * @param provider The {@link JAXBContextProvider} to use.
75: * @since 1.0.0
76: */
77: public static void setContextProvider(@NotNull JAXBContextProvider provider) {
78: jaxbContextProvider = provider;
79: }
80:
81: /**
82: * Gets the default {@link JAXBContext} available.
83: *
84: * @return The default {@link JAXBContext} available.
85: * @throws JAXBException See {@link JAXBContextFactory#createContext(Class[], Map)}
86: * @since 1.0.0
87: */
88: private static JAXBContext getContext() throws JAXBException {
89: JAXBContext context;
90: try {
91: context = jaxbContextProvider.getJAXBContext();
92:
93:• if (context == null) {
94: LOG.warn("No JAXBContext found! Creating one using JAXBContextFactory.createContext(...).");
95: context = JAXBContextFactory.createContext(new Class[]{}, null);
96: }
97: } catch (KapuaException | NullPointerException ex) {
98: LOG.warn("No JAXBContextProvider provided or error while getting one! Creating one using JAXBContextFactory.createContext(...).", ex);
99: context = JAXBContextFactory.createContext(new Class[]{}, null);
100: }
101: return context;
102: }
103:
104: //
105: // Marshall
106: //
107:
108: /**
109: * Marshals the given {@link Object} to an XML {@link String}.
110: *
111: * @param object The {@link Object} to marshal.
112: * @return The Json {@link String} representation of the object.
113: * @throws JAXBException See {@link Marshaller#marshal(Object, Writer)}.
114: * @since 1.0.0
115: */
116: public static String marshal(@NotNull Object object)
117: throws JAXBException {
118: try (StringWriter sw = new StringWriter()) {
119: marshal(object, sw);
120: return sw.toString();
121: } catch (IOException ioe) {
122: // This exception is thrown when operations are performed on a closed Writer.
123: // This Writer is self-contained in this XmlUtil class and .marshal(...) is not closing it.
124: // Therefore if this IOException occurs, something really bad happened.
125: throw new IllegalStateException("XmlUtil.marshal(Object) Writer was found unexpectedly closed!", ioe);
126: }
127: }
128:
129: /**
130: * Marshals the given XML {@link Object} into the given {@link Writer} as XML representation.
131: *
132: * @param object The {@link Object} to marshall.
133: * @param writer The {@link Writer} to use.
134: * @throws JAXBException See {@link Marshaller#marshal(Object, Writer)}
135: * @since 1.0.0
136: */
137: public static void marshal(@NotNull Object object, @NotNull Writer writer)
138: throws JAXBException {
139: marshal(object, writer, Collections.emptyMap());
140: }
141:
142: /**
143: * Marshals the given {@link Object} to an JSON {@link String}.
144: *
145: * @param object The {@link Object} to marshal.
146: * @return The Json {@link String} representation of the object.
147: * @throws JAXBException See {@link Marshaller#marshal(Object, Writer)}.
148: * @since 1.0.0
149: */
150: public static String marshalJson(@NotNull Object object)
151: throws JAXBException {
152: try (StringWriter sw = new StringWriter()) {
153: marshalJson(object, sw);
154: return sw.toString();
155: } catch (IOException ioe) {
156: // This exception is thrown when operations are performed on a closed Writer.
157: // This Writer is self-contained in this XmlUtil class and .marshal(...) is not closing it.
158: // Therefore if this IOException occurs, something really bad happened.
159: throw new IllegalStateException("XmlUtil.marshalJson(Object) Writer was found unexpectedly closed!", ioe);
160: }
161: }
162:
163: /**
164: * Marshals the given XML {@link Object} into the given {@link Writer} as JSON representation.
165: *
166: * @param object The {@link Object} to marshall.
167: * @param writer The {@link Writer} to use.
168: * @throws JAXBException See {@link Marshaller#marshal(Object, Writer)}
169: * @since 1.0.0
170: */
171: public static void marshalJson(@NotNull Object object, @NotNull Writer writer)
172: throws JAXBException {
173:
174: Map<String, Object> jsonProperties = new HashMap<>();
175: jsonProperties.put(MarshallerProperties.JSON_INCLUDE_ROOT, false);
176: jsonProperties.put(MarshallerProperties.MEDIA_TYPE, "application/json");
177:
178: marshal(object, writer, jsonProperties);
179: }
180:
181: /**
182: * Marshals the given {@link Object} into the given {@link Writer}, configuring the
183: * {@link Marshaller} with the given additional {@link Properties}.
184: *
185: * @param object The {@link Object} to marshall.
186: * @param writer The {@link Writer} to use.
187: * @param additionalProperties Additional {@link Properties} to configure the {@link Marshaller}
188: * @throws JAXBException See {@link Marshaller#marshal(Object, Writer)}
189: * @since 1.5.0
190: */
191: private static void marshal(@NotNull Object object, @NotNull Writer writer, @NotNull Map<String, Object> additionalProperties) throws JAXBException {
192:
193: JAXBContext context = getContext();
194:
195: Marshaller marshaller = context.createMarshaller();
196: marshaller.setSchema(null);
197: marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
198:
199: additionalProperties.forEach((key, value) -> {
200: try {
201: marshaller.setProperty(key, value);
202: } catch (PropertyException e) {
203: LOG.error("Marshaller invalid property: {}", key, e);
204: }
205: });
206:
207: ValidationEventCollector eventCollector = new ValidationEventCollector();
208: marshaller.setEventHandler(eventCollector);
209:
210: try {
211: marshaller.marshal(object, writer);
212: } catch (JAXBException je) {
213: throw je;
214: } catch (Exception e) {
215: throw new MarshalException(e.getMessage(), e);
216: }
217:
218:• if (eventCollector.hasEvents()) {
219:• for (ValidationEvent valEvent : eventCollector.getEvents()) {
220:• if (valEvent.getSeverity() != ValidationEvent.WARNING) {
221: throw new MarshalException(valEvent.getMessage(), valEvent.getLinkedException());
222: }
223: }
224: }
225: }
226:
227: //
228: // Unmarshall
229: //
230:
231: /**
232: * Unmarshals the given XML {@link String} as the given {@link Class type}.
233: *
234: * @param objectString The {@link String} serialized.
235: * @param type The {@link Class} type to unmarshal to.
236: * @return The unmarshalled {@link Object}.
237: * @throws JAXBException See {@link #getContext()}.
238: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
239: * @since 1.0.0
240: */
241: public static <T> T unmarshal(@NotNull String objectString, @NotNull Class<T> type)
242: throws JAXBException, SAXException {
243: try (Reader reader = new StringReader(objectString)) {
244: return unmarshal(reader, type);
245: } catch (IOException ioe) {
246: // This exception is thrown when operations are performed on a closed Reader.
247: // This Reader is self-contained in this XmlUtil class and .unmarshal(...) is not closing it.
248: // Therefore if this IOException occurs, something really bad happened.
249: throw new IllegalStateException("XmlUtil.unmarshal(String, Class) Reader was found unexpectedly closed!", ioe);
250: }
251: }
252:
253: /**
254: * Unmarshals the given XML {@link Reader} as the given {@link Class type}.
255: *
256: * @param reader The source {@link Reader}.
257: * @param type The {@link Class} type to unmarshal to.
258: * @return The unmarshalled {@link Object}.
259: * @throws JAXBException See {@link #getContext()}.
260: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
261: * @since 1.0.0
262: */
263: public static <T> T unmarshal(@NotNull Reader reader, @NotNull Class<T> type)
264: throws JAXBException, SAXException {
265: return unmarshal(reader, type, null);
266: }
267:
268: /**
269: * Unmarshals the given XML {@link String} as the given {@link Class type} according to the given namespace {@link java.net.URI}
270: *
271: * @param objectString The {@link String} serialized.
272: * @param type The {@link Class} type to unmarshal to.
273: * @param namespaceUri The namespace {@link java.net.URI} to use
274: * @return The unmarshalled {@link Object}.
275: * @throws JAXBException See {@link #getContext()}.
276: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
277: * @since 1.0.0
278: */
279: public static <T> T unmarshal(@NotNull String objectString, @NotNull Class<T> type, @Nullable String namespaceUri)
280: throws JAXBException, SAXException {
281: try (Reader reader = new StringReader(objectString)) {
282: return unmarshal(reader, type, namespaceUri);
283: } catch (IOException ioe) {
284: // This exception is thrown when operations are performed on a closed Reader.
285: // This Reader is self-contained in this XmlUtil class and .unmarshal(...) is not closing it.
286: // Therefore if this IOException occurs, something really bad happened.
287: throw new IllegalStateException("XmlUtil.unmarshal(String, Class, String) Reader was found unexpectedly closed!", ioe);
288: }
289: }
290:
291:
292: /**
293: * Unmarshals the given XML {@link Reader} as the given {@link Class type} according to the given namespace {@link java.net.URI}.
294: *
295: * @param reader The source {@link Reader}.
296: * @param type The {@link Class} type to unmarshal to.
297: * @param namespaceUri The namespace {@link java.net.URI} to use
298: * @return The unmarshalled {@link Object}.
299: * @throws JAXBException See {@link #getContext()}.
300: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
301: * @since 1.0.0
302: */
303: public static <T> T unmarshal(@NotNull Reader reader, @NotNull Class<T> type, @Nullable String namespaceUri)
304: throws JAXBException, SAXException {
305: return unmarshal(reader, type, namespaceUri, Collections.emptyMap());
306: }
307:
308: /**
309: * Unmarshals the given JSON {@link String} as the given {@link Class type}
310: *
311: * @param objectString The {@link String} serialized.
312: * @param type The {@link Class} type to unmarshal to.
313: * @return The unmarshalled {@link Object}.
314: * @throws JAXBException See {@link #getContext()}.
315: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
316: * @since 1.5.0
317: */
318: public static <T> T unmarshalJson(@NotNull String objectString, @NotNull Class<T> type) throws JAXBException, SAXException {
319: return unmarshalJson(objectString, type, null);
320: }
321:
322: /**
323: * Unmarshals the given JSON {@link String} as the given {@link Class type} according to the given namespace {@link java.net.URI}.
324: *
325: * @param objectString The {@link String} serialized.
326: * @param type The {@link Class} type to unmarshal to.
327: * @param namespaceUri The namespace {@link java.net.URI} to use
328: * @return The unmarshalled {@link Object}.
329: * @throws JAXBException See {@link #getContext()}.
330: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
331: * @since 1.0.0
332: */
333: public static <T> T unmarshalJson(@NotNull String objectString, @NotNull Class<T> type, @Nullable String namespaceUri)
334: throws JAXBException, SAXException {
335: try (Reader reader = new StringReader(objectString)) {
336: return unmarshalJson(reader, type, namespaceUri);
337: } catch (IOException ioe) {
338: // This exception is thrown when operations are performed on a closed Reader.
339: // This Reader is self-contained in this XmlUtil class and .unmarshal(...) is not closing it.
340: // Therefore if this IOException occurs, something really bad happened.
341: throw new IllegalStateException("XmlUtil.unmarshalJson(String, Class, String) Reader was found unexpectedly closed!", ioe);
342: }
343: }
344:
345: /**
346: * Unmarshals the given JSON {@link Reader} as the given {@link Class type} according to the given namespace {@link java.net.URI}.
347: *
348: * @param reader The {@link Reader} serialized.
349: * @param type The {@link Class} type to unmarshal to.
350: * @param namespaceUri The namespace {@link java.net.URI} to use
351: * @return The unmarshalled {@link Object}.
352: * @throws JAXBException See {@link #getContext()}.
353: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
354: * @since 1.0.0
355: */
356: public static <T> T unmarshalJson(@NotNull Reader reader, @NotNull Class<T> type, @Nullable String namespaceUri)
357: throws JAXBException, SAXException {
358:
359: Map<String, Object> jsonProperties = new HashMap<>();
360: jsonProperties.put(MarshallerProperties.MEDIA_TYPE, "application/json");
361: jsonProperties.put(MarshallerProperties.JSON_INCLUDE_ROOT, false);
362:
363: return unmarshal(reader, type, namespaceUri, jsonProperties);
364: }
365:
366:
367: /**
368: * Unmarshals the given JSON {@link Reader} as the given {@link Class type} according to the given namespace {@link java.net.URI},
369: * configuring the {@link Unmarshaller} with the given additional {@link Properties}.
370: *
371: * @param reader The {@link Reader} serialized.
372: * @param type The {@link Class} type to unmarshal to.
373: * @param namespaceUri The namespace {@link java.net.URI} to use
374: * @param additionalProperties Additional {@link Properties} to configure the {@link Unmarshaller}
375: * @param <T> The return {@link Class}
376: * @return The unmarshalled {@link Object}.
377: * @throws JAXBException See {@link #getContext()}.
378: * @throws SAXException See {@link XMLReaderFactory#createXMLReader()}.
379: */
380: private static <T> T unmarshal(@NotNull Reader reader, @NotNull Class<T> type, @Nullable String namespaceUri, @NotNull Map<String, Object> additionalProperties) throws JAXBException, SAXException {
381: JAXBContext context = getContext();
382:
383: Unmarshaller unmarshaller = context.createUnmarshaller();
384: unmarshaller.setSchema(null);
385:
386: additionalProperties.forEach((key, value) -> {
387: try {
388: unmarshaller.setProperty(key, value);
389: } catch (PropertyException e) {
390: LOG.error("Unmarshaller invalid property: {}", key, e);
391: }
392: });
393:
394: ValidationEventCollector eventCollector = new ValidationEventCollector();
395: unmarshaller.setEventHandler(eventCollector);
396:
397: SAXSource saxSource;
398:• if (Strings.isNullOrEmpty(namespaceUri)) {
399: saxSource = new SAXSource(new InputSource(reader));
400: } else {
401: XmlNamespaceFilter filter = new XmlNamespaceFilter(namespaceUri, true);
402:
403: XMLReader xmlReader = XMLReaderFactory.createXMLReader();
404: filter.setParent(xmlReader);
405:
406: saxSource = new SAXSource(filter, new InputSource(reader));
407: }
408:
409: JAXBElement<T> jaxbElement;
410: try {
411: jaxbElement = unmarshaller.unmarshal(saxSource, type);
412: } catch (JAXBException e) {
413: throw e;
414: } catch (Exception e) {
415: throw new UnmarshalException(e.getMessage(), e);
416: }
417:
418:• if (eventCollector.hasEvents()) {
419:• for (ValidationEvent valEvent : eventCollector.getEvents()) {
420: LOG.warn("Unmarshal Validation Event: {} - {}", valEvent.getSeverity(), valEvent.getMessage(), valEvent.getLinkedException());
421:
422:• if (valEvent.getSeverity() != ValidationEvent.WARNING) {
423: String msg = MessageFormat.format("Line {0}, Col: {1}.{2}\tError message: {3}{2}\tLinked exception message:{4}",
424: valEvent.getLocator().getLineNumber(),
425: valEvent.getLocator().getColumnNumber(),
426: SystemUtils.LINE_SEPARATOR,
427:• valEvent.getMessage() != null ? valEvent.getMessage() : "",
428:• valEvent.getLinkedException() != null ? valEvent.getLinkedException().getMessage() : "");
429: throw new UnmarshalException(msg, valEvent.getLinkedException());
430: }
431: }
432: }
433: return jaxbElement.getValue();
434: }
435: }