-
Notifications
You must be signed in to change notification settings - Fork 43
/
XmlProvider.java
163 lines (149 loc) · 6.17 KB
/
XmlProvider.java
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package jrds.starter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.log4j.Level;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* @author bacchell A provider is used for XML to solve multi thread problems
*
* As each one is parsed by one and only one thread, it we used one
* provider by host, we can simply solved the concurency problem and
* reuse factory and parser without too many risks
*
*/
public class XmlProvider extends Starter {
private ThreadLocal<DocumentBuilder> localDocumentBuilder = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
DocumentBuilderFactory instance = DocumentBuilderFactory.newInstance();
instance.setIgnoringComments(true);
instance.setValidating(false);
try {
return instance.newDocumentBuilder();
} catch (ParserConfigurationException e) {
log(Level.FATAL, e, "No Document builder available");
return null;
}
}
};
private ThreadLocal<XPath> localXpath = new ThreadLocal<XPath>() {
@Override
protected XPath initialValue() {
return XPathFactory.newInstance().newXPath();
}
};
public long findUptimeByDate(Document d, String startTimePath, String currentTimePath, DateFormat pattern) {
XPath xpather = localXpath.get();
try {
Node startTimeNode = (Node) xpather.evaluate(startTimePath, d, XPathConstants.NODE);
String startTimeString = startTimeNode.getTextContent();
Date startTime = pattern.parse(startTimeString);
Node currentTimeNode = (Node) xpather.evaluate(currentTimePath, d, XPathConstants.NODE);
String currentTimeString = currentTimeNode.getTextContent();
Date currentTime = pattern.parse(currentTimeString);
return (currentTime.getTime() - startTime.getTime()) / 1000;
} catch (XPathExpressionException e) {
log(Level.ERROR, e, "Time not found");
} catch (ParseException e) {
log(Level.ERROR, e, "Date not parsed with pattern " + ((SimpleDateFormat) pattern).toPattern());
}
return 0;
}
public long findUptime(Document d, String upTimePath) {
long uptime = 0;
if(upTimePath == null) {
log(Level.ERROR, "No xpath for the uptime for " + this);
return 0;
}
try {
XPath xpather = localXpath.get();
Node upTimeNode = (Node) xpather.evaluate(upTimePath, d, XPathConstants.NODE);
if(upTimeNode != null) {
log(Level.TRACE, "Will parse uptime: %s", upTimeNode.getTextContent());
String dateString = upTimeNode.getTextContent();
uptime = jrds.Util.parseStringNumber(dateString, 0L);
}
log(Level.ALL, "uptime is %d", uptime);
} catch (XPathExpressionException e) {
log(Level.ERROR, e, "Uptime not found");
}
return uptime;
}
public void fileFromXpaths(Document d, Set<String> xpaths, Map<String, Number> oldMap) {
XPath xpather = localXpath.get();
for(String xpath: xpaths) {
try {
log(Level.TRACE, "Will search the xpath \"%s\"", xpath);
if(xpath == null || "".equals(xpath))
continue;
Node n = (Node) xpather.evaluate(xpath, d, XPathConstants.NODE);
Double value;
if(n != null) {
log(Level.TRACE, "%s", n);
value = jrds.Util.parseStringNumber(n.getTextContent(), Double.NaN);
oldMap.put(xpath, value);
}
} catch (XPathExpressionException e) {
log(Level.ERROR, "Invalid XPATH : " + xpath + " for " + this);
} catch (NumberFormatException e) {
log(Level.WARN, e, "value read from %s not parsable", xpath);
}
}
log(Level.TRACE, "Values found: %s", oldMap);
}
public Document getDocument(InputSource stream) {
DocumentBuilder dbuilder = localDocumentBuilder.get();
Document d = null;
log(Level.TRACE, "%s %s %s started %s@%s", stream, dbuilder, isStarted(), getClass().getName(), Integer.toHexString(hashCode()));
try {
dbuilder.reset();
d = dbuilder.parse(stream);
log(Level.TRACE, "just parsed a %s", d.getDocumentElement().getTagName());
} catch (SAXException e) {
log(Level.ERROR, e, "Invalid XML: %s", e.getMessage());
} catch (IOException e) {
log(Level.ERROR, e, "IO Exception getting values: %s", e.getMessage());
}
return d;
}
public Document getDocument(InputStream stream) {
return getDocument(new InputSource(stream));
}
public Document getDocument(Reader stream) {
return getDocument(new InputSource(stream));
}
/**
* Used to get an empty document
*
* @return an empty document
*/
public Document getDocument() {
DocumentBuilder dbuilder = localDocumentBuilder.get();
dbuilder.reset();
return dbuilder.newDocument();
}
public NodeList getNodeList(Document d, String xpath) throws XPathExpressionException {
return (NodeList) localXpath.get().evaluate(xpath, d, XPathConstants.NODESET);
}
public Node getNode(Document d, String xpath) throws XPathExpressionException {
return (Node) localXpath.get().evaluate(xpath, d, XPathConstants.NODE);
}
}