You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by re...@apache.org on 2024/05/17 16:54:49 UTC
(jackrabbit-oak) branch trunk updated: OAK-10760: oak-core should check namespace registry consistency on st… (#1447)
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 <ma...@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;
+ }
}