This is an automated email from the ASF dual-hosted git repository. reschke pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push: new 43619290a5 OAK-10760: oak-core should check namespace registry consistency on st… (#1447) 43619290a5 is described below commit 43619290a5ebdc9c60aa9d1929f796e5033f59da Author: mbaedke <manfred.bae...@gmail.com> AuthorDate: Fri May 17 18:54:43 2024 +0200 OAK-10760: oak-core should check namespace registry consistency on st… (#1447) * OAK-10760: oak-core should check namespace registry consistency on startup Implemented. * OAK-10760: oak-core should check namespace registry consistency on startup Removed Guava usage, improved log messages. * OAK-10760: oak-core should check namespace registry consistency on startup Added flag to avoid multiple consistency checks. * OAK-10760: oak-core should check namespace registry consistency on startup Fixed property miscount and URI encoding issues. --- .../plugins/name/ReadOnlyNamespaceRegistry.java | 76 +++++++++++++++++++++- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/ReadOnlyNamespaceRegistry.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/ReadOnlyNamespaceRegistry.java index 87d12054d4..ddf6509ce0 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/ReadOnlyNamespaceRegistry.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/ReadOnlyNamespaceRegistry.java @@ -16,7 +16,6 @@ */ package org.apache.jackrabbit.oak.plugins.name; -import static org.apache.jackrabbit.guava.common.collect.Iterables.toArray; import static java.util.Collections.emptyList; import static org.apache.jackrabbit.oak.api.Type.STRING; import static org.apache.jackrabbit.oak.api.Type.STRINGS; @@ -26,11 +25,19 @@ import javax.jcr.NamespaceRegistry; import javax.jcr.RepositoryException; import javax.jcr.UnsupportedRepositoryOperationException; +import org.apache.jackrabbit.util.Text; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.spi.namespace.NamespaceConstants; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; /** * Read-only namespace registry. Used mostly internally when access to the @@ -42,12 +49,19 @@ import org.jetbrains.annotations.NotNull; public class ReadOnlyNamespaceRegistry implements NamespaceRegistry, NamespaceConstants { + private static final Logger LOG = LoggerFactory.getLogger(ReadOnlyNamespaceRegistry.class); + + private static volatile boolean CONSISTENCY_CHECKED; + protected final Tree namespaces; protected final Tree nsdata; public ReadOnlyNamespaceRegistry(Root root) { this.namespaces = root.getTree(NAMESPACES_PATH); this.nsdata = namespaces.getChild(REP_NSDATA); + if (!CONSISTENCY_CHECKED) { + checkConsistency(); + } } private Iterable<String> getNSData(String name) { @@ -74,12 +88,16 @@ public class ReadOnlyNamespaceRegistry @Override @NotNull public String[] getPrefixes() { - return toArray(getNSData(REP_PREFIXES), String.class); + List<String> prefixes = new ArrayList(); + getNSData(REP_PREFIXES).forEach(prefixes::add); + return prefixes.toArray(new String[prefixes.size()]); } @Override @NotNull public String[] getURIs() { - return toArray(getNSData(REP_URIS), String.class); + List<String> uris = new ArrayList<>(); + getNSData(REP_URIS).forEach(uris::add); + return uris.toArray(new String[uris.size()]); } @Override @NotNull @@ -112,4 +130,56 @@ public class ReadOnlyNamespaceRegistry "No namespace prefix registered for URI " + uri); } + protected void checkConsistency() { + final String jcrPrimaryType = "jcr:primaryType"; + List<String> prefixes = Arrays.asList(getPrefixes()); + List<String> encodedUris = Arrays.stream(getURIs()).map(Namespaces::encodeUri).collect(Collectors.toList()); + if (prefixes.size() != encodedUris.size()) { + LOG.error("The namespace registry is inconsistent: found {} registered namespace prefixes and {} registered namespace URIs. The numbers have to be equal.", prefixes.size(), encodedUris.size()); + } + int mappedPrefixCount = 0; + for (PropertyState propertyState : namespaces.getProperties()) { + String prefix = propertyState.getName(); + if (!prefix.equals(jcrPrimaryType)) { + mappedPrefixCount++; + if (!prefixes.contains(prefix)) { + LOG.error("The namespace registry is inconsistent: namespace prefix {} is mapped to a namespace URI, but not contained in the list of registered namespace prefixes.", prefix); + } + try { + getURI(prefix); + } catch (NamespaceException e) { + LOG.error("The namespace registry is inconsistent: namespace prefix {} is not mapped to a namespace URI.", prefix); + } + } + } + //prefixes contains the unmapped empty prefix + if (mappedPrefixCount + 1 != prefixes.size()) { + LOG.error("The namespace registry is inconsistent: found {} mapped namespace prefixes and {} registered namespace prefixes. The numbers have to be equal.", mappedPrefixCount, prefixes.size()); + } + int mappedUriCount = 0; + for (PropertyState propertyState : nsdata.getProperties()) { + String encodedUri = propertyState.getName(); + switch (encodedUri) { + case REP_PREFIXES: + case REP_URIS: + case jcrPrimaryType: + break; + default: + mappedUriCount++; + if (!encodedUris.contains(encodedUri)) { + LOG.error("The namespace registry is inconsistent: encoded namespace URI {} is mapped to a namespace prefix, but not contained in the list of registered namespace URIs.", encodedUri); + } + try { + getPrefix(Text.unescapeIllegalJcrChars(encodedUri)); + } catch (NamespaceException e) { + LOG.error("The namespace registry is inconsistent: namespace URI {} is not mapped to a namespace prefix.", encodedUri); + } + } + } + //encodedUris contains the unmapped empty namespace URI + if (mappedUriCount + 1 != encodedUris.size()) { + LOG.error("The namespace registry is inconsistent: found {} mapped namespace URIs and {} registered namespace URIs. The numbers have to be equal.", mappedUriCount, encodedUris.size()); + } + CONSISTENCY_CHECKED = true; + } }