You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2022/02/20 17:17:53 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-558 expose StandaloneManagerProvider from vault-core (#210)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new d5ddc51  JCRVLT-558 expose StandaloneManagerProvider from vault-core (#210)
d5ddc51 is described below

commit d5ddc51b07a3e7707c7d373e5c25a0a5edac857d
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sun Feb 20 18:17:45 2022 +0100

    JCRVLT-558 expose StandaloneManagerProvider from vault-core (#210)
    
    Introduce CndUtil for reusing parsing from Sling bundle headers
---
 vault-core/bnd.bnd                                 |  3 +
 vault-core/pom.xml                                 |  5 ++
 .../jackrabbit/vault/fs/io/DocViewParser.java      |  6 ++
 .../vault/util/StandaloneManagerProvider.java      | 51 ++++++++-------
 .../src/main/resources/default-nodetypes.cnd       |  0
 .../spi/impl/nodetype/NodeTypeValidator.java       |  5 +-
 .../impl/nodetype/NodeTypeValidatorFactory.java    | 72 +++++----------------
 .../spi/util/classloaderurl/CndUtil.java           | 73 ++++++++++++++++++++++
 .../spi/util/classloaderurl/URLFactory.java        | 20 ++++++
 .../spi/util/classloaderurl/package-info.java      |  2 +-
 .../impl/nodetype/JcrNodeTypeMetaDataImplTest.java |  5 +-
 .../spi/impl/nodetype/NodeTypeValidatorTest.java   |  3 +-
 12 files changed, 161 insertions(+), 84 deletions(-)

diff --git a/vault-core/bnd.bnd b/vault-core/bnd.bnd
index 87e44d7..5f1c845 100644
--- a/vault-core/bnd.bnd
+++ b/vault-core/bnd.bnd
@@ -18,12 +18,15 @@ Import-Package: org.apache.jackrabbit.spi2dav;resolution:=optional,\
                             org.apache.sling.jcr.api;resolution:=optional,\
                             org.apache.jackrabbit.*;version=!,\
                             *
+# include complete packages (all transitive dependencies lead to Import-Package instructions)
+-conditionalpackage: org.apache.jackrabbit.jcr2spi.*
 DynamicImport-Package: *
 -includeresource: @txw2-[0-9.]*.jar!/com/sun/xml/txw2/output/(IndentingXMLStreamWriter|DelegatingXMLStreamWriter).*,\
                   @woodstox-core-[0-9.]*.jar!/!module-info.class,\
                   @stax2-api-[0-9.]*.jar!/!module-info.class,\
                   @maven-artifact-[0-9.]*.jar!/org/apache/maven/artifact/versioning/ComparableVersion*.class,\
                   @h2-[0-9.]*.jar!/org/h2/util/CloseWatcher*.class
+                  
 # whitelist the private reference usage in Packaging.getJcrPackageRegistry(Session)
 -fixupmessages:"Export org.apache.jackrabbit.vault.packaging,  has 1,  private references [org.apache.jackrabbit.vault.packaging.registry.impl]"; \
     restrict:=warning; \
diff --git a/vault-core/pom.xml b/vault-core/pom.xml
index bfa22f7..0e56fcc 100644
--- a/vault-core/pom.xml
+++ b/vault-core/pom.xml
@@ -153,6 +153,11 @@
             <artifactId>jackrabbit-spi2dav</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-jcr2spi</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <!-- JCR Stuff -->
         <dependency>
             <groupId>javax.jcr</groupId>
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewParser.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewParser.java
index d8f1074..a9438c0 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewParser.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewParser.java
@@ -138,6 +138,12 @@ public class DocViewParser {
         }
     }
 
+    /**
+     * Don't forget to reset the reader or use a new reader before parsing the xml.
+     * @param reader the reader from which to read the XML
+     * @return {@code true} in case the given source is Document View XML format
+     * @throws IOException
+     */
     public static boolean isDocView(Reader reader) throws IOException {
         // read a couple of chars...1024 should be enough
         char[] buffer = new char[1024];
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeManagerProvider.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/StandaloneManagerProvider.java
similarity index 83%
rename from vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeManagerProvider.java
rename to vault-core/src/main/java/org/apache/jackrabbit/vault/util/StandaloneManagerProvider.java
index 05146d8..db91ed0 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeManagerProvider.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/StandaloneManagerProvider.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.vault.validation.spi.impl.nodetype;
+package org.apache.jackrabbit.vault.util;
 
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -22,8 +22,6 @@ import java.io.Reader;
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.NamespaceException;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
@@ -61,25 +59,35 @@ import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeStorageImpl;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 import org.apache.jackrabbit.value.ValueFactoryImpl;
 import org.jetbrains.annotations.NotNull;
+import org.osgi.annotation.versioning.ProviderType;
 
-public class NodeTypeManagerProvider implements ManagerProvider, NamespaceStorage {
+/**
+ * A {@link ManagerProvider} which works without an underlying JCR repository.
+ * Useful for dealing with namespaces and node types outside the repository context.
+ */
+@ProviderType
+public final class StandaloneManagerProvider implements ManagerProvider, NamespaceStorage {
 
     // namespace related helpers
     private final @NotNull NamespaceMapping namespaceMapping;
     private final @NotNull NamespaceRegistry namespaceRegistry;
     private final @NotNull NamespaceResolver namespaceResolver;
     private final @NotNull NamePathResolver npResolver;
-    
-    // nodetype related helpers
+
+    // node type related helpers
     private final @NotNull NodeTypeStorage nodeTypeStorage;
     private final @NotNull NodeTypeRegistryImpl nodeTypeRegistry;
     private final @NotNull NodeTypeManagerImpl nodeTypeManager;
-    
+
     private final @NotNull ItemDefinitionProvider itemDefinitionProvider;
 
-    public NodeTypeManagerProvider() throws IOException, RepositoryException, ParseException {
+    public StandaloneManagerProvider() throws IOException, RepositoryException, ParseException {
+        this(true);
+    }
+
+    public StandaloneManagerProvider(boolean registerDefaultNodeTypes) throws IOException, RepositoryException, ParseException {
         namespaceMapping = new NamespaceMapping();
-        // add default mapping, the rest comes from the CDN provided via the reader
+        // add default mapping, the rest comes from the CND provided via the reader
         namespaceMapping.setMapping(NamespaceRegistry.PREFIX_EMPTY, NamespaceRegistry.NAMESPACE_EMPTY);
         namespaceRegistry = new NamespaceRegistryImpl(this);
         namespaceResolver = new RegistryNamespaceResolver(namespaceRegistry);
@@ -88,11 +96,12 @@ public class NodeTypeManagerProvider implements ManagerProvider, NamespaceStorag
         nodeTypeRegistry = NodeTypeRegistryImpl.create(nodeTypeStorage, namespaceRegistry);
         nodeTypeManager = new NodeTypeManagerImpl(nodeTypeRegistry, this);
         itemDefinitionProvider = new ItemDefinitionProviderImpl(nodeTypeRegistry, null, null);
-        // always provide default nodetypes
-        try (Reader reader = new InputStreamReader(
-                this.getClass().getResourceAsStream("/default-nodetypes.cnd"),
-                StandardCharsets.US_ASCII)) {
-            registerNodeTypes(reader);
+        if (registerDefaultNodeTypes) {
+            try (Reader reader = new InputStreamReader(
+                    this.getClass().getResourceAsStream("/default-nodetypes.cnd"),
+                    StandardCharsets.US_ASCII)) {
+                registerNodeTypes(reader);
+            }
         }
     }
 
@@ -107,12 +116,12 @@ public class NodeTypeManagerProvider implements ManagerProvider, NamespaceStorag
 
     @Override
     public @NotNull NameResolver getNameResolver() {
-        return npResolver;
+        return getNamePathResolver();
     }
 
     @Override
     public @NotNull PathResolver getPathResolver() {
-        return npResolver;
+        return getNamePathResolver();
     }
 
     @Override
@@ -180,24 +189,22 @@ public class NodeTypeManagerProvider implements ManagerProvider, NamespaceStorag
     }
 
     @Override
-    public String getPrefix(String uri) throws NamespaceException, RepositoryException {
+    public String getPrefix(String uri) throws RepositoryException {
         return namespaceMapping.getPrefix(uri);
     }
 
     @Override
-    public String getURI(String prefix) throws NamespaceException, RepositoryException {
+    public String getURI(String prefix) throws RepositoryException {
         return namespaceMapping.getURI(prefix);
     }
 
     @Override
-    public void registerNamespace(String prefix, String uri)
-            throws NamespaceException, UnsupportedRepositoryOperationException, AccessDeniedException, RepositoryException {
+    public void registerNamespace(String prefix, String uri) throws RepositoryException {
         namespaceMapping.setMapping(prefix, uri);
     }
 
     @Override
-    public void unregisterNamespace(String uri)
-            throws NamespaceException, UnsupportedRepositoryOperationException, AccessDeniedException, RepositoryException {
+    public void unregisterNamespace(String uri) throws RepositoryException {
         namespaceMapping.removeMapping(uri);
     }
 }
diff --git a/vault-validation/src/main/resources/default-nodetypes.cnd b/vault-core/src/main/resources/default-nodetypes.cnd
similarity index 100%
rename from vault-validation/src/main/resources/default-nodetypes.cnd
rename to vault-core/src/main/resources/default-nodetypes.cnd
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
index cca7bc2..e4c8140 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
@@ -50,6 +50,7 @@ import org.apache.jackrabbit.value.StringValue;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.util.DocViewNode2;
 import org.apache.jackrabbit.vault.util.DocViewProperty2;
+import org.apache.jackrabbit.vault.util.StandaloneManagerProvider;
 import org.apache.jackrabbit.vault.validation.ValidationExecutor;
 import org.apache.jackrabbit.vault.validation.spi.DocumentViewXmlValidator;
 import org.apache.jackrabbit.vault.validation.spi.JcrPathValidator;
@@ -74,13 +75,13 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
     private final ValidationMessageSeverity severityForUnknownNodeTypes;
     private final ValidationMessageSeverity severityForDefaultNodeTypeViolations;
     private final DocViewPropertyValueFactory docViewPropertyValueFactory;
-    private final NodeTypeManagerProvider ntManagerProvider;
+    private final StandaloneManagerProvider ntManagerProvider;
     private final Set<String> loggedUnknownNodeTypeMessages;
 
     private final @NotNull Name defaultType;
     private JcrNodeTypeMetaData currentNodeTypeMetaData;
 
-    public NodeTypeValidator(boolean isIncremental, @NotNull WorkspaceFilter filter, @NotNull NodeTypeManagerProvider ntManagerProvider,
+    public NodeTypeValidator(boolean isIncremental, @NotNull WorkspaceFilter filter, @NotNull StandaloneManagerProvider ntManagerProvider,
             @NotNull Name defaultPrimaryNodeType, @NotNull ValidationMessageSeverity defaultSeverity,
             @NotNull ValidationMessageSeverity severityForUnknownNodeTypes, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations)
             throws ConstraintViolationException, NoSuchNodeTypeException {
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
index aab39ef..99c75b0 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
@@ -17,28 +17,24 @@
 package org.apache.jackrabbit.vault.validation.spi.impl.nodetype;
 
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.JarURLConnection;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
-import java.util.jar.Manifest;
 
 import javax.jcr.RepositoryException;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.commons.cnd.ParseException;
+import org.apache.jackrabbit.vault.util.StandaloneManagerProvider;
 import org.apache.jackrabbit.vault.validation.spi.ValidationContext;
 import org.apache.jackrabbit.vault.validation.spi.ValidationMessageSeverity;
 import org.apache.jackrabbit.vault.validation.spi.Validator;
 import org.apache.jackrabbit.vault.validation.spi.ValidatorFactory;
 import org.apache.jackrabbit.vault.validation.spi.ValidatorSettings;
+import org.apache.jackrabbit.vault.validation.spi.util.classloaderurl.CndUtil;
 import org.apache.jackrabbit.vault.validation.spi.util.classloaderurl.URLFactory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -63,8 +59,6 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
     /** Comma-separated list of name spaces that are known as valid (even if not defined in the CND files). Use syntax "prefix1=ns-uri1,prefix2=nsuri2,...". */
     public static final String OPTION_VALID_NAMESPACES = "validNameSpaces";
 
-
-
     private static final Logger LOGGER = LoggerFactory.getLogger(NodeTypeValidatorFactory.class);
 
     @Override
@@ -109,61 +103,27 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
         }
 
         try {
-            NodeTypeManagerProvider ntManagerProvider = null;
-            ntManagerProvider = new NodeTypeManagerProvider();
-            for (String cndUrl : resolveJarUrls(cndUrls.split(","))) {
-                try (Reader reader = new InputStreamReader(URLFactory.createURL(cndUrl).openStream(), StandardCharsets.US_ASCII)) {
-                    LOGGER.info("Register node types from {}", cndUrl);
-                    ntManagerProvider.registerNodeTypes(reader);
-                } catch (RepositoryException | IOException | ParseException e) {
-                    throw new IllegalArgumentException("Error loading node types from CND at " + cndUrl, e);
+            StandaloneManagerProvider managerProvider = new StandaloneManagerProvider();
+            URLFactory.processUrlStreams(CndUtil.resolveJarUrls(Arrays.asList(cndUrls.split(","))), t -> {
+                try {
+                    managerProvider.registerNodeTypes(t);
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
                 }
-            }
+                catch (ParseException | RepositoryException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            });
             for (Map.Entry<String, String> entry : validNameSpaces.entrySet()) {
-                ntManagerProvider.registerNamespace(entry.getKey(), entry.getValue());
+                managerProvider.registerNamespace(entry.getKey(), entry.getValue());
             }
-            return new NodeTypeValidator(context.isIncremental(), context.getFilter(), ntManagerProvider, ntManagerProvider.getNameResolver().getQName(defaultNodeType), settings.getDefaultSeverity(),
+            return new NodeTypeValidator(context.isIncremental(), context.getFilter(), managerProvider, managerProvider.getNameResolver().getQName(defaultNodeType), settings.getDefaultSeverity(),
                     severityForUnknownNodetypes, severityForDefaultNodeTypeViolations);
         } catch (IOException | RepositoryException | ParseException e) {
             throw new IllegalArgumentException("Error loading default node type " + defaultNodeType, e);
         }
     }
 
-    /**
-     * Resolve URLs pointing to JARs with META-INF/MANIFEST carrying a {@code Sling-Nodetypes} header
-     * @param urls
-     * @return
-     */
-    static List<String> resolveJarUrls(String... urls) {
-        List<String> resolvedUrls = new LinkedList<>();
-        for (String url : urls) {
-            url = url.trim();
-            if (url.endsWith(".jar")) {
-                // https://docs.oracle.com/javase/7/docs/api/java/net/JarURLConnection.html
-                URL jarUrl;
-                try {
-                    jarUrl = URLFactory.createURL("jar:" + url + "!/");
-                    JarURLConnection jarConnection = (JarURLConnection)jarUrl.openConnection();
-                    Manifest manifest = jarConnection.getManifest();
-                    String slingNodetypes = manifest.getMainAttributes().getValue("Sling-Nodetypes");
-                    // split by "," and generate new JAR Urls
-                    if (slingNodetypes == null) {
-                        LOGGER.warn("No 'Sling-Nodetypes' header found in manifest of '{}'", jarUrl);
-                    } else {
-                        for (String nodetype : slingNodetypes.split(",")) {
-                            resolvedUrls.add(jarUrl.toString() + nodetype.trim());
-                        }
-                    }
-                } catch (IOException e) {
-                    throw new IllegalArgumentException("Could not read from JAR " + url, e);
-                }
-            } else {
-                resolvedUrls.add(url);
-            }
-        }
-        return resolvedUrls;
-    }
-
     static Map<String,String> parseNamespaces(String optionValue) {
         Map<String,String> result = new HashMap<>();
         String[] namespaces = optionValue.split(",");
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/CndUtil.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/CndUtil.java
new file mode 100644
index 0000000..9b7c2a4
--- /dev/null
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/CndUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.vault.validation.spi.util.classloaderurl;
+
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.jar.Manifest;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ProviderType
+public final class CndUtil {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CndUtil.class);
+
+    private CndUtil() {
+        // static util methods only
+    }
+    /**
+     * Resolve URLs pointing to JARs with META-INF/MANIFEST carrying a {@code Sling-Nodetypes} header
+     * @param urls
+     * @return
+     */
+    public static List<String> resolveJarUrls(List<String> urls) {
+        List<String> resolvedUrls = new LinkedList<>();
+        for (String url : urls) {
+            url = url.trim();
+            if (url.endsWith(".jar")) {
+                // https://docs.oracle.com/javase/7/docs/api/java/net/JarURLConnection.html
+                URL jarUrl;
+                try {
+                    jarUrl = URLFactory.createURL("jar:" + url + "!/");
+                    JarURLConnection jarConnection = (JarURLConnection)jarUrl.openConnection();
+                    Manifest manifest = jarConnection.getManifest();
+                    String slingNodetypes = manifest.getMainAttributes().getValue("Sling-Nodetypes");
+                    // split by "," and generate new JAR Urls
+                    if (slingNodetypes == null) {
+                        LOGGER.warn("No 'Sling-Nodetypes' header found in manifest of '{}'", jarUrl);
+                    } else {
+                        for (String nodetype : slingNodetypes.split(",")) {
+                            resolvedUrls.add(jarUrl.toString() + nodetype.trim());
+                        }
+                    }
+                } catch (IOException e) {
+                    throw new IllegalArgumentException("Could not read from JAR " + url, e);
+                }
+            } else {
+                resolvedUrls.add(url);
+            }
+        }
+        return resolvedUrls;
+    }
+
+}
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/URLFactory.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/URLFactory.java
index 517168a..96956e4 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/URLFactory.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/URLFactory.java
@@ -16,9 +16,19 @@
  */
 package org.apache.jackrabbit.vault.validation.spi.util.classloaderurl;
 
+import java.io.IOException;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.osgi.annotation.versioning.ProviderType;
 
+@ProviderType
 public class URLFactory {
     public static final String TCCL_PROTOCOL_PREFIX = "tccl:";
     
@@ -38,4 +48,14 @@ public class URLFactory {
         }
         return url;
     }
+
+    public static void processUrlStreams(List<String> urls, Consumer<Reader> readerProcessor) {
+        for (String url : urls) {
+            try (Reader reader = new InputStreamReader(URLFactory.createURL(url).openStream(), StandardCharsets.US_ASCII)) {
+                readerProcessor.accept(reader);
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Error loading content from " + url, e);
+            }
+        }
+    }
 }
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/package-info.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/package-info.java
index c23cd0a..a5380a1 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/package-info.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/util/classloaderurl/package-info.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.0")
+@Version("1.1.0")
 package org.apache.jackrabbit.vault.validation.spi.util.classloaderurl;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
index e827ff7..09bac29 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
@@ -40,6 +40,7 @@ import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.value.ValueFactoryImpl;
 import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
 import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
+import org.apache.jackrabbit.vault.util.StandaloneManagerProvider;
 import org.apache.jackrabbit.vault.validation.AnyValidationViolationMessageMatcher;
 import org.apache.jackrabbit.vault.validation.ValidationExecutorTest;
 import org.apache.jackrabbit.vault.validation.spi.NodeContext;
@@ -53,7 +54,7 @@ import org.junit.Test;
 
 public class JcrNodeTypeMetaDataImplTest {
 
-    private NodeTypeManagerProvider ntManagerProvider;
+    private StandaloneManagerProvider ntManagerProvider;
 
     private JcrNodeTypeMetaDataImpl root;
 
@@ -62,7 +63,7 @@ public class JcrNodeTypeMetaDataImplTest {
 
     @Before
     public void setUp() throws IOException, RepositoryException, ParseException {
-        ntManagerProvider = new NodeTypeManagerProvider();
+        ntManagerProvider = new StandaloneManagerProvider();
         root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
     }
 
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
index 8004744..b89d4e6 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
@@ -40,6 +40,7 @@ import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
 import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.apache.jackrabbit.vault.util.DocViewNode2;
 import org.apache.jackrabbit.vault.util.DocViewProperty2;
+import org.apache.jackrabbit.vault.util.StandaloneManagerProvider;
 import org.apache.jackrabbit.vault.validation.AnyValidationViolationMessageMatcher;
 import org.apache.jackrabbit.vault.validation.ValidationExecutorTest;
 import org.apache.jackrabbit.vault.validation.spi.NodeContext;
@@ -70,7 +71,7 @@ public class NodeTypeValidatorTest {
 
     static NodeTypeValidator createValidator(WorkspaceFilter filter, Name defaultNodeType, String... cndUrls)
             throws IOException, RepositoryException, ParseException {
-        NodeTypeManagerProvider ntManagerProvider = new NodeTypeManagerProvider();
+        StandaloneManagerProvider ntManagerProvider = new StandaloneManagerProvider();
         for (String cndUrl : cndUrls) {
             try (Reader reader = new InputStreamReader(URLFactory.createURL(cndUrl).openStream(), StandardCharsets.US_ASCII)) {
                 ntManagerProvider.registerNodeTypes(reader);