Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UniPro Pull Request: Performance Fixes #4

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
128 changes: 79 additions & 49 deletions src/main/java/ru/relex/c14n2/DOMCanonicalizerHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.apache.commons.lang3.StringUtils;

/**
* C14N2 canonicalizer.
Expand All @@ -32,6 +34,11 @@ class DOMCanonicalizerHandler {
private static final String CF = "&#x%s;";
private static final String C = ":";

private static final byte[] XD = {'&','#','x','D',';'};
private static final byte[] GT = {'&','g','t',';'};
private static final byte[] LT = {'&','l','t',';'};
private static final byte[] AMP = {'&','a','m','p',';'};

private List<Node> excludeList;
private Parameters parameters;
private StringBuffer outputBuffer;
Expand Down Expand Up @@ -178,7 +185,7 @@ protected void processElement(Node node) {

output.append(">");

outputBuffer.append(output);
StringUtils.join(outputBuffer,output);
}

/**
Expand Down Expand Up @@ -207,7 +214,7 @@ protected void processEndElement(Node node) {
bEnd = true;
}

outputBuffer.append(output);
StringUtils.join(outputBuffer,output);
}

/**
Expand All @@ -216,6 +223,7 @@ protected void processEndElement(Node node) {
* @param node
* text node
*/

protected void processText(Node node) {
LOGGER.debug("processText: {}", node);
if (getNodeDepth(node) < 2) {
Expand All @@ -224,24 +232,32 @@ protected void processText(Node node) {

String text = node.getNodeValue() != null ? node.getNodeValue() : "";

text = processText(text, false);

StringBuffer value = new StringBuffer();
StringBuffer value = new StringBuffer(text.length());
for (int i = 0; i < text.length(); i++) {
char codepoint = text.charAt(i);
if (codepoint == 13) {
value.append(String.format(CF, Integer.toHexString(codepoint)
.toUpperCase()));
} else {
if (codepoint == '&') {
value.append(AMP);
}
else if (codepoint == '<') {
value.append(LT);
}
else if (codepoint == '>') {
value.append(GT);
}
else if (codepoint == 0xd) {
value.append(XD);
}
else {
value.append(codepoint);
}
}
text = value.toString();

if (parameters.isTrimTextNodes()) {
boolean b = true;
for (int ai = 0; ai < node.getParentNode().getAttributes().getLength(); ai++) {
Node attr = node.getParentNode().getAttributes().item(ai);
NamedNodeMap attrs = node.getParentNode().getAttributes();
for (int ai = 0; ai < attrs.getLength(); ai++) {
Node attr = attrs.item(ai);
if (isInExcludeList(attr))
continue;
if (XML.equals(getNodePrefix(attr))
Expand All @@ -252,7 +268,7 @@ && getLocalName(attr).equals("space")) {
}
}
if (b) {
text = text.trim();
text = StringUtils.trim(text);
}
}

Expand All @@ -267,7 +283,7 @@ && getLocalName(attr).equals("space")) {
for (QNameAwareParameter en : parameters.getQnameAwareElements()) {
if (nodeName.equals(en.getName())
&& en.getNs().equals(attrPrfxNcp.getUri())) {
text = ncp.getNewPrefix() + text.substring(XSD.length());
text = StringUtils.join(ncp.getNewPrefix(), StringUtils.substring(text, XSD.length()));
}
}
}
Expand All @@ -278,10 +294,10 @@ && getLocalName(attr).equals("space")) {
Node prntNode = node.getParentNode();
String nodeName = getLocalName(prntNode);
String nodePrefix = getNodePrefix(prntNode);
String nodeText = node.getTextContent();
NamespaceContextParams ncp = getLastElement(nodePrefix);
for (QNameAwareParameter en : parameters.getQnameAwareXPathElements()) {
if (nodeName.equals(en.getName()) && ncp.getUri().equals(en.getNs())) {
String nodeText = node.getTextContent();
NSContext nsContext = xpathesNsMap.get(nodeText);
List<String> xpathNs = nsContext.getXpathNs();
StringBuffer sb = new StringBuffer(nodeText.length());
Expand All @@ -293,9 +309,9 @@ && getLocalName(attr).equals("space")) {
for (int i = 0; i < words.size(); i++) {
Object obj = words.elementAt(i);
String word = obj.toString();
int idx = nodeText.indexOf(word, baseTextIdx);
int idx = StringUtils.indexOf(nodeText, word, baseTextIdx);
if (idx != baseTextIdx) {
sb.append(nodeText.substring(baseTextIdx, idx));
sb.append(StringUtils.substring(nodeText, baseTextIdx, idx));
baseTextIdx = idx;
}
if (!(obj instanceof XString)
Expand All @@ -306,7 +322,7 @@ && getLocalName(attr).equals("space")) {
if (it.hasNext())
ns = it.next();
else {
sb.append(nodeText.substring(baseTextIdx));
sb.append(StringUtils.substring(nodeText, baseTextIdx));
break;
}
} else {
Expand All @@ -320,7 +336,7 @@ && getLocalName(attr).equals("space")) {
}
}

outputBuffer.append(text);
StringUtils.join(outputBuffer,text);
}

/**
Expand All @@ -343,7 +359,7 @@ protected void processPI(Node node) {
if (bStart && getNodeDepth(node) == 1) {
output.append("\n");
}
outputBuffer.append(output);
StringUtils.join(outputBuffer,output);
}

/**
Expand All @@ -365,7 +381,8 @@ protected void processComment(Node node) {
if (bStart && getNodeDepth(node) == 1) {
output.append("\n");
}
outputBuffer.append(output);
StringUtils.join(outputBuffer,output);

}

/**
Expand All @@ -376,7 +393,8 @@ protected void processComment(Node node) {
*/
protected void processCData(Node node) {
LOGGER.debug("processCData:" + node);
outputBuffer.append(processText(node.getNodeValue(), false));
StringUtils.join(outputBuffer,processText(node.getNodeValue(), false));

}

/**
Expand Down Expand Up @@ -462,20 +480,18 @@ else if (prev.isHasOutput() == null || prev.isHasOutput())
* DOM node
*/
private void removeNamespaces(Node node) {
for (String prefix : namespaces.keySet()) {
List<NamespaceContextParams> nsLevels = namespaces.get(prefix);
while (!nsLevels.isEmpty()
&& getLastElement(prefix).getDepth() >= getNodeDepth(node)) {
int nDepth = getNodeDepth(node);
for (Iterator<Map.Entry<String, List<NamespaceContextParams>>> it = namespaces.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, List<NamespaceContextParams>> entry = it.next();
List<NamespaceContextParams> nsLevels = entry.getValue();
while (!nsLevels.isEmpty() &&
nsLevels.get(nsLevels.size() - 1).getDepth() >= nDepth) {

nsLevels.remove(nsLevels.size() - 1);
}
}

Iterator<Entry<String, List<NamespaceContextParams>>> it = namespaces
.entrySet().iterator();
while (it.hasNext()) {
Entry<String, List<NamespaceContextParams>> en = it.next();
if (en.getValue().size() == 0)
if (nsLevels.isEmpty()) {
it.remove();
}
}
}

Expand Down Expand Up @@ -565,6 +581,16 @@ private List<NamespaceContextParams> processNamespaces(Node node) {

List<NamespaceContextParams> outNSList = new ArrayList<NamespaceContextParams>();

String nPrefix = getNodePrefix(node);

String childText = null;
if (parameters.getQnameAwareElements().size() > 0 ||
(parameters.getQnameAwareXPathElements().size() > 0 &&
node.getChildNodes().getLength() == 1)) {

childText = node.getTextContent();
}

int depth = getNodeDepth(node);
for (String prefix : namespaces.keySet()) {
NamespaceContextParams ncp = getLastElement(prefix);
Expand All @@ -577,7 +603,7 @@ private List<NamespaceContextParams> processNamespaces(Node node) {
ncp = entry;
}
if (ncp.isHasOutput() != null && !ncp.isHasOutput()) {
if (isPrefixVisible(node, prefix)) {
if (isPrefixVisible(node, prefix, childText, nPrefix)) {
NamespaceContextParams entry = ncp.clone();
entry.setPrefix(prefix);
outNSList.add(entry);
Expand Down Expand Up @@ -663,20 +689,22 @@ private void addNamespaces(Node node) {
* @return Returns true if prefix is shown in the output of the node, false -
* otherwise.
*/
private boolean isPrefixVisible(Node node, String prefix) {
String nodePrefix = getNodePrefix(node);
if (nodePrefix.equals(prefix)) {
private boolean isPrefixVisible(Node node, String prefix, String childText, String nPrefix) {

if (nPrefix.equals(prefix)) {
return true;
}

String nodeLocalName = getLocalName(node);
if (parameters.getQnameAwareElements().size() > 0) {
NamespaceContextParams ncp = getLastElement(prefix);
String prfx = ncp.getPrefix();
String childText = node.getTextContent();
if (childText == null) {
childText = node.getTextContent();
}
if (childText != null && childText.startsWith(prfx + C)
&& node.getChildNodes().getLength() == 1) {
NamespaceContextParams attrPrfxNcp = getLastElement(nodePrefix);
NamespaceContextParams attrPrfxNcp = getLastElement(nPrefix);
for (QNameAwareParameter en : parameters.getQnameAwareElements()) {
if (nodeLocalName.equals(en.getName())
&& en.getNs().equals(attrPrfxNcp.getUri())) {
Expand All @@ -687,8 +715,10 @@ private boolean isPrefixVisible(Node node, String prefix) {
}
if (parameters.getQnameAwareXPathElements().size() > 0
&& node.getChildNodes().getLength() == 1) {
NamespaceContextParams ncp = getLastElement(nodePrefix);
String childText = node.getTextContent();
NamespaceContextParams ncp = getLastElement(nPrefix);
if (childText == null) {
childText = node.getTextContent();
}
for (QNameAwareParameter en : parameters.getQnameAwareXPathElements()) {
if (nodeLocalName.equals(en.getName())
&& ncp.getUri().equals(en.getNs())) {
Expand Down Expand Up @@ -749,16 +779,16 @@ private boolean isPrefixVisible(Node node, String prefix) {
* @return replacement text
*/
private String processText(String text, boolean bAttr) {
text = text.replace("&", "&amp;");
text = text.replace("<", "&lt;");
text = StringUtils.replace(text,"&", "&amp;");
text = StringUtils.replace(text, "<", "&lt;");
if (!bAttr) {
text = text.replace(">", "&gt;");
text = StringUtils.replace(text, ">", "&gt;");
} else {
text = text.replace("\"", "&quot;");
text = text.replace("#xA", "&#xA;");
text = text.replace("#x9", "&#x9;");
text = StringUtils.replace(text, "\"", "&quot;");
text = StringUtils.replace(text, "#xA", "&#xA;");
text = StringUtils.replace(text, "#x9", "&#x9;");
}
text = text.replace("#xD", "&#xD;");
text = StringUtils.replace(text, "#xD", "&#xD;");
return text;
}

Expand Down Expand Up @@ -818,8 +848,8 @@ private String getNodePrefix(Node node) {
String name = node.getNodeName();
int idx = name.indexOf(C);
if (idx > -1)
return name.substring(0, idx);
return StringUtils.substring(name,0, idx);
}
return prfx;
}
}
}