fix TreeMap NPE in XML namespace context

This commit is contained in:
Jörg Prante 2018-01-30 16:13:06 +01:00
parent c2e4bb8646
commit 5289b080a1
3 changed files with 36 additions and 23 deletions

View file

@ -1,7 +1,6 @@
package org.xbib.content.resource; package org.xbib.content.resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -22,11 +21,15 @@ public final class IRINamespaceContext extends XmlNamespaceContext {
*/ */
private static final String DEFAULT_RESOURCE = private static final String DEFAULT_RESOURCE =
XmlNamespaceContext.class.getPackage().getName().replace('.', '/') + '/' + "namespace"; XmlNamespaceContext.class.getPackage().getName().replace('.', '/') + '/' + "namespace";
private static IRINamespaceContext instance; private static IRINamespaceContext instance;
private static final IRINamespaceContext DEFAULT_CONTEXT = newInstance(DEFAULT_RESOURCE); private static final IRINamespaceContext DEFAULT_CONTEXT = newInstance(DEFAULT_RESOURCE);
private List<String> sortedNamespacesByPrefixLength; private List<String> sortedNamespacesByPrefixLength;
private IRINamespaceContext() { private IRINamespaceContext() {
super();
} }
private IRINamespaceContext(ResourceBundle bundle) { private IRINamespaceContext(ResourceBundle bundle) {
@ -60,26 +63,30 @@ public final class IRINamespaceContext extends XmlNamespaceContext {
@Override @Override
public void addNamespace(String prefix, String namespace) { public void addNamespace(String prefix, String namespace) {
super.addNamespace(prefix, namespace); super.addNamespace(prefix, namespace);
sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values()); synchronized (lock) {
// sort from longest to shortest prefix for successful matching sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values());
Collections.sort(sortedNamespacesByPrefixLength, (s1, s2) -> { // sort from longest to shortest prefix for successful matching
Integer l1 = s1.length(); sortedNamespacesByPrefixLength.sort((s1, s2) -> {
Integer l2 = s2.length(); Integer l1 = s1.length();
return l2.compareTo(l1); Integer l2 = s2.length();
}); return l2.compareTo(l1);
});
}
} }
public IRINamespaceContext add(Map<String, String> map) { public IRINamespaceContext add(Map<String, String> map) {
for (Map.Entry<String, String> e : map.entrySet()) { for (Map.Entry<String, String> e : map.entrySet()) {
super.addNamespace(e.getKey(), e.getValue()); super.addNamespace(e.getKey(), e.getValue());
} }
sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values()); synchronized (lock) {
// sort from longest to shortest prefix for successful matching sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values());
Collections.sort(sortedNamespacesByPrefixLength, (s1, s2) -> { // sort from longest to shortest prefix for successful matching
Integer l1 = s1.length(); sortedNamespacesByPrefixLength.sort((s1, s2) -> {
Integer l2 = s2.length(); Integer l1 = s1.length();
return l2.compareTo(l1); Integer l2 = s2.length();
}); return l2.compareTo(l1);
});
}
return this; return this;
} }
@ -100,12 +107,15 @@ public final class IRINamespaceContext extends XmlNamespaceContext {
return null; return null;
} }
// drop fragment (useful for resource counters in fragments) // drop fragment (useful for resource counters in fragments)
final String s = dropfragment ? new IRI(uri.getScheme(), uri.getSchemeSpecificPart(), null).toString() : uri.toString(); String s = dropfragment ? new IRI(uri.getScheme(), uri.getSchemeSpecificPart(), null).toString() : uri.toString();
// search from longest to shortest namespace prefix synchronized (lock) {
if (sortedNamespacesByPrefixLength != null) { // search from longest to shortest namespace prefix
for (String ns : sortedNamespacesByPrefixLength) { if (sortedNamespacesByPrefixLength != null) {
if (s.startsWith(ns)) { for (String ns : sortedNamespacesByPrefixLength) {
return getPrefix(ns) + ':' + s.substring(ns.length()); if (s.startsWith(ns)) {
s = getPrefix(ns) + ':' + s.substring(ns.length());
break;
}
} }
} }
} }

View file

@ -31,9 +31,12 @@ public class XmlNamespaceContext implements NamespaceContext {
private final SortedMap<String, Set<String>> prefixes; private final SortedMap<String, Set<String>> prefixes;
protected final Object lock;
protected XmlNamespaceContext() { protected XmlNamespaceContext() {
this.namespaces = new TreeMap<>(); this.namespaces = new TreeMap<>();
this.prefixes = new TreeMap<>(); this.prefixes = new TreeMap<>();
this.lock = new Object();
} }
protected XmlNamespaceContext(ResourceBundle bundle) { protected XmlNamespaceContext(ResourceBundle bundle) {
@ -83,7 +86,7 @@ public class XmlNamespaceContext implements NamespaceContext {
public void addNamespace(String prefix, String namespace) { public void addNamespace(String prefix, String namespace) {
if (prefix != null && namespace != null) { if (prefix != null && namespace != null) {
synchronized (namespaces) { synchronized (lock) {
namespaces.put(prefix, namespace); namespaces.put(prefix, namespace);
if (prefixes.containsKey(namespace)) { if (prefixes.containsKey(namespace)) {
prefixes.get(namespace).add(prefix); prefixes.get(namespace).add(prefix);

View file

@ -1,6 +1,6 @@
group = org.xbib group = org.xbib
name = content name = content
version = 1.2.3 version = 1.2.4
jackson.version = 2.8.11 jackson.version = 2.8.11
xbib-net.version = 1.0.0 xbib-net.version = 1.0.0