blob: f347643ea438da23a42cf1b1822efa104edade7d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package com.p4square.ccbapi;
import com.p4square.ccbapi.exception.CCBParseException;
import com.p4square.ccbapi.model.CCBAPIResponse;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.concurrent.ConcurrentHashMap;
/**
* CCBXmlBinder is used to bind XML responses to CCBAPIResponse implementations.
*
* This class is thread-safe.
*/
public class CCBXmlBinder {
private final XMLInputFactory xmlInputFactory;
private final ConcurrentHashMap<Class<? extends CCBAPIResponse>, JAXBContext> jaxbContextCache;
public CCBXmlBinder() {
xmlInputFactory = XMLInputFactory.newFactory();
jaxbContextCache = new ConcurrentHashMap<>();
}
public <T extends CCBAPIResponse> T bindResponseXML(InputStream response, Class<T> responseClass)
throws CCBParseException {
try {
final XMLStreamReader xmlReader = xmlInputFactory.createXMLStreamReader(response);
final JAXBContext jaxbContext = getJAXBContext(responseClass);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// Skip ahead to the response entity.
while (xmlReader.hasNext()) {
xmlReader.next();
if (xmlReader.isStartElement() && "response".equalsIgnoreCase(xmlReader.getLocalName())) {
// Parse and return the response.
// If the response cannot be parsed a JAXBException will be thrown.
return (T) unmarshaller.unmarshal(xmlReader);
}
}
// If we reach this point then the response did not contain a response element.
throw new CCBParseException("Response did not contain a response element.");
} catch (XMLStreamException | JAXBException e) {
throw new CCBParseException("Failed to parse response.", e);
}
}
/**
* Find or create the JAXBContext for a CCBAPIResponse implementation.
*
* @param responseClass The response implementation class.
* @return a JAXBContext which can be used to unmarshell the responseClass.
*/
private JAXBContext getJAXBContext(Class<? extends CCBAPIResponse> responseClass) {
if (!jaxbContextCache.containsKey(responseClass)) {
synchronized (jaxbContextCache) {
// Check again to be sure.
if (!jaxbContextCache.containsKey(responseClass)) {
try {
final JAXBContext jaxbContext = JAXBContext.newInstance(responseClass);
jaxbContextCache.put(responseClass, jaxbContext);
} catch (JAXBException e) {
throw new AssertionError("Could not construct JAXBContext for " + responseClass.getName(), e);
}
}
}
}
return jaxbContextCache.get(responseClass);
}
}
|