/*
 * 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.sling.testing.mock.sling.loader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.contentparser.api.ContentParser;
import org.apache.sling.contentparser.api.ParserOptions;
import org.apache.sling.contentparser.json.JSONParserFeature;
import org.apache.sling.contentparser.json.JSONParserOptions;
import org.apache.sling.contentparser.json.internal.JSONContentParser;
import org.apache.sling.contentparser.xml.jcr.internal.JCRXMLContentParser;
import org.apache.sling.fsprovider.internal.FsResourceProvider;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.apache.sling.testing.mock.osgi.MapUtil;
import org.apache.sling.testing.mock.osgi.MockOsgi;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.builder.ImmutableValueMap;
import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

/**
 * Imports JSON data and binary data into Sling resource hierarchy.
 * After all import operations from json or binaries {@link ResourceResolver#commit()} is called (when autocommit mode is active).
 */
public final class ContentLoader {

    private static final String CONTENTTYPE_OCTET_STREAM = "application/octet-stream";

    // set of resource or property names that are ignored for all resource resolver types
    private static final Set<String> SHARED_IGNORED_NAMES = Stream.of(
            JcrConstants.JCR_BASEVERSION,
            JcrConstants.JCR_PREDECESSORS,
            JcrConstants.JCR_SUCCESSORS,
            JcrConstants.JCR_VERSIONHISTORY,
            "jcr:checkedOut",
            "jcr:isCheckedOut",
            "rep:policy")
            .collect(Collectors.toSet());

    // set of resource or property names that are ignored when other resource resolver types than JCR_OAK are used
    private static final Set<String> MOCK_IGNORED_NAMES = Stream.concat(
            SHARED_IGNORED_NAMES.stream(), Stream.of(
            JcrConstants.JCR_MIXINTYPES))
            .collect(Collectors.toSet());

    // set of resource or property names that are ignored when JCR_OAK resource resolver type (= a real repo impl) is used
    private static final Set<String> OAK_IGNORED_NAMES = Stream.concat(
            SHARED_IGNORED_NAMES.stream(), Stream.of(
            JcrConstants.JCR_UUID,
            JcrConstants.JCR_CREATED))
            .collect(Collectors.toSet());

    private final ResourceResolver resourceResolver;
    private final BundleContext bundleContext;
    private final boolean autoCommit;
    private final Set<String> ignoredNames;
    private final ContentParser jsonParser;
    private final ParserOptions jsonParserOptions;
    private final ContentParser fileVaultXmlParser;
    private final ParserOptions fileVaultXmlParserOptions;

    /**
     * @param resourceResolver Resource resolver
     */
    public ContentLoader(@NotNull ResourceResolver resourceResolver) {
        this(resourceResolver, null);
    }

    /**
     * @param resourceResolver Resource resolver
     * @param bundleContext Bundle context
     */
    public ContentLoader(@NotNull ResourceResolver resourceResolver, @Nullable BundleContext bundleContext) {
        this(resourceResolver, bundleContext, true);
    }

    /**
     * @param resourceResolver Resource resolver
     * @param bundleContext Bundle context
     * @param autoCommit Automatically commit changes after loading content (default: true)
     */
    public ContentLoader(@NotNull ResourceResolver resourceResolver, @Nullable BundleContext bundleContext, boolean autoCommit) {
        this(resourceResolver, bundleContext, autoCommit, null);
    }

    /**
     * @param resourceResolver Resource resolver
     * @param bundleContext Bundle context
     * @param autoCommit Automatically commit changes after loading content (default: true)
     * @param resourceResolverType Resource resolver type.
     */
    public ContentLoader(@NotNull ResourceResolver resourceResolver, @Nullable BundleContext bundleContext, boolean autoCommit,
            @Nullable ResourceResolverType resourceResolverType) {
        this.resourceResolver = resourceResolver;
        this.bundleContext = bundleContext;
        this.autoCommit = autoCommit;
        this.ignoredNames = getIgnoredNamesForResourceResolverType(resourceResolverType);

        this.jsonParserOptions = new JSONParserOptions()
            .withFeatures(EnumSet.of(JSONParserFeature.COMMENTS, JSONParserFeature.QUOTE_TICK))
            .detectCalendarValues(true)
            .ignorePropertyNames(this.ignoredNames)
            .ignoreResourceNames(this.ignoredNames);
        this.jsonParser = new JSONContentParser();

        this.fileVaultXmlParserOptions = new ParserOptions()
                .detectCalendarValues(true)
                .ignorePropertyNames(this.ignoredNames)
                .ignoreResourceNames(this.ignoredNames);
        this.fileVaultXmlParser = new JCRXMLContentParser();
    }

    private final Set<String> getIgnoredNamesForResourceResolverType(ResourceResolverType resourceResolverType) {
        if (resourceResolverType == null || resourceResolverType == ResourceResolverType.JCR_OAK) {
            return OAK_IGNORED_NAMES;
        }
        else {
            return MOCK_IGNORED_NAMES;
        }
    }

    /**
     * Import content of JSON file into repository.
     * @param classpathResourceOrFile Classpath resource URL or file path for JSON content
     * @param parentResource Parent resource
     * @param childName Name of child resource to create with JSON content
     * @return Resource
     */
    public @NotNull Resource json(@NotNull String classpathResourceOrFile, @NotNull Resource parentResource, @NotNull String childName) {
        return json(classpathResourceOrFile, parentResource.getPath() + "/" + childName);
    }

    /**
     * Import content of JSON file into repository. Auto-creates parent
     * hierarchies as nt:unstrucured nodes if missing.
     * @param classpathResourceOrFile Classpath resource URL or file path for JSON content
     * @param destPath Path to import the JSON content to
     * @return Resource
     */
    public @NotNull Resource json(@NotNull String classpathResourceOrFile, @NotNull String destPath) {
        return processInputStreamFromClasspathOrFilesystem(classpathResourceOrFile, is -> json(is, destPath));
    }

    /**
     * Import content of JSON file into repository.
     * @param inputStream Input stream with JSON content
     * @param parentResource Parent resource
     * @param childName Name of child resource to create with JSON content
     * @return Resource
     */
    public @NotNull Resource json(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String childName) {
        return json(inputStream, parentResource.getPath() + "/" + childName);
    }

    /**
     * Import content of JSON file into repository. Auto-creates parent
     * hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream with JSON content
     * @param destPath Path to import the JSON content to
     * @return Resource
     */
    public @NotNull Resource json(@NotNull InputStream inputStream, @NotNull String destPath) {
        return mountParsedFile(inputStream, destPath, jsonParser, jsonParserOptions);
    }

    /**
     * Import content of FileVault XML file into repository.
     * @param classpathResourceOrFile Classpath resource URL or file path to single FileVault XML file (usually <code>.content.xml</code>)
     * @param parentResource Parent resource
     * @param childName Name of child resource to create with Filevault content
     * @return Resource
     */
    public @NotNull Resource fileVaultXml(@NotNull String classpathResourceOrFile, @NotNull Resource parentResource, @NotNull String childName) {
        return fileVaultXml(classpathResourceOrFile, parentResource.getPath() + "/" + childName);
    }

    /**
     * Import content of FileVault XML file into repository. Auto-creates parent
     * hierarchies as nt:unstrucured nodes if missing.
     * @param classpathResourceOrFile Classpath resource URL or file path to single FileVault XML file (usually <code>.content.xml</code>)
     * @param destPath Path to import the Filevault content to
     * @return Resource
     */
    public @NotNull Resource fileVaultXml(@NotNull String classpathResourceOrFile, @NotNull String destPath) {
        return processInputStreamFromClasspathOrFilesystem(classpathResourceOrFile, is -> fileVaultXml(is, destPath));
    }

    /**
     * Import content of FileVault XML file into repository.
     * @param inputStream Input stream with Filevault content
     * @param parentResource Parent resource
     * @param childName Name of child resource to create with Filevault content
     * @return Resource
     */
    public @NotNull Resource fileVaultXml(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String childName) {
        return fileVaultXml(inputStream, parentResource.getPath() + "/" + childName);
    }

    /**
     * Import content of FileVault XML file into repository. Auto-creates parent
     * hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream with Filevault content
     * @param destPath Path to import the Filevault content to
     * @return Resource
     */
    public @NotNull Resource fileVaultXml(@NotNull InputStream inputStream, @NotNull String destPath) {
        return mountParsedFile(inputStream, destPath, fileVaultXmlParser, fileVaultXmlParserOptions);
    }

    @SuppressWarnings("null")
    private @NotNull Resource mountParsedFile(@NotNull InputStream inputStream, @NotNull String destPath,
            @NotNull ContentParser contentParser, @NotNull ParserOptions parserOptions) {
        try {
            String parentPath = ResourceUtil.getParent(destPath);
            String childName = ResourceUtil.getName(destPath);

            if (parentPath == null) {
                throw new IllegalArgumentException("Path has no parent: " + destPath);
            }

            Resource parentResource = resourceResolver.getResource(parentPath);
            if (parentResource == null) {
                parentResource = createResourceHierarchy(parentPath);
            }
            if (parentResource.getChild(childName) != null) {
                throw new IllegalArgumentException("Resource does already exist: " + destPath);
            }

            LoaderContentHandler contentHandler = new LoaderContentHandler(destPath, resourceResolver);
            contentParser.parse(contentHandler, inputStream, parserOptions);
            if (autoCommit) {
                resourceResolver.commit();
            }
            return resourceResolver.getResource(destPath);
        }
        catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private @NotNull Resource createResourceHierarchy(@NotNull String path) {
        String parentPath = ResourceUtil.getParent(path);
        if (parentPath == null) {
            throw new IllegalArgumentException("Path has no parent: " + path);
        }
        Resource parentResource = resourceResolver.getResource(parentPath);
        if (parentResource == null) {
            parentResource = createResourceHierarchy(parentPath);
        }
        Map<String, Object> props = new HashMap<String, Object>();
        props.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
        try {
            return resourceResolver.create(parentResource, ResourceUtil.getName(path), props);
        } catch (PersistenceException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
     * auto-detected from either {@code classpathResourceOrFile} or {@code path}.
     * @param classpathResourceOrFile Classpath resource URL or file path for binary file.
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull String classpathResourceOrFile, @NotNull String path) {
        return binaryFile(classpathResourceOrFile, path, detectMimeTypeFromNames(classpathResourceOrFile, path));
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing.
     * @param classpathResourceOrFile Classpath resource URL or file path for binary file.
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull String classpathResourceOrFile, @NotNull String path, @NotNull String mimeType) {
        return processInputStreamFromClasspathOrFilesystem(classpathResourceOrFile, is -> binaryFile(is, path, mimeType));
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
     * auto-detected from resource name.
     * @param inputStream Input stream for binary data
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull InputStream inputStream, @NotNull String path) {
        return binaryFile(inputStream, path, detectMimeTypeFromNames(path));
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream for binary data
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull InputStream inputStream, @NotNull String path, @NotNull String mimeType) {
        String parentPath = ResourceUtil.getParent(path, 1);
        String name = ResourceUtil.getName(path);
        if (parentPath == null) {
            throw new IllegalArgumentException("Path has no parent: " + path);
        }
        Resource parentResource = resourceResolver.getResource(parentPath);
        if (parentResource == null) {
            parentResource = createResourceHierarchy(parentPath);
        }
        return binaryFile(inputStream, parentResource, name, mimeType);
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
     * auto-detected from resource name.
     * @param inputStream Input stream for binary data
     * @param parentResource Parent resource
     * @param name Resource name for nt:file
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String name) {
        return binaryFile(inputStream, parentResource, name, detectMimeTypeFromNames(name));
    }

    /**
     * Import binary file as nt:file binary node into repository. Auto-creates
     * parent hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream for binary data
     * @param parentResource Parent resource
     * @param name Resource name for nt:file
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryFile(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String name, @NotNull String mimeType) {
        try {
            Resource file = resourceResolver.create(parentResource, name,
                    ImmutableValueMap.of(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_FILE));
            resourceResolver.create(file, JcrConstants.JCR_CONTENT,
                    ImmutableValueMap.of(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_RESOURCE,
                            JcrConstants.JCR_DATA, inputStream,
                            JcrConstants.JCR_MIMETYPE, mimeType));
            if (autoCommit) {
                resourceResolver.commit();
            }
            return file;
        } catch (PersistenceException ex) {
            throw new RuntimeException("Unable to create resource at " + parentResource.getPath() + "/" + name, ex);
        }
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
     * type is auto-detected from {@code classpathResourceOrFile} or {@code path}.
     * @param classpathResourceOrFile Classpath resource URL or file path for binary file.
     * @param path Path to mount binary data to (parent nodes created automatically)
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull String classpathResourceOrFile, @NotNull String path) {
        return binaryResource(classpathResourceOrFile, path, detectMimeTypeFromNames(classpathResourceOrFile, path));
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
     * @param classpathResourceOrFile Classpath resource URL or file path for binary file.
     * @param path Path to mount binary data to (parent nodes created automatically)
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull String classpathResourceOrFile, @NotNull String path, @NotNull String mimeType) {
        return processInputStreamFromClasspathOrFilesystem(classpathResourceOrFile, is -> binaryResource(is, path, mimeType));
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
     * type is auto-detected from resource name.
     * @param inputStream Input stream for binary data
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull InputStream inputStream, @NotNull String path) {
        return binaryResource(inputStream, path, detectMimeTypeFromNames(path));
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream for binary data
     * @param path Path to mount binary data to (parent nodes created
     *            automatically)
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull InputStream inputStream, @NotNull String path, @NotNull String mimeType) {
        String parentPath = ResourceUtil.getParent(path, 1);
        String name = ResourceUtil.getName(path);
        if (parentPath == null) {
            throw new IllegalArgumentException("Path has no parent: " + path);
        }
        Resource parentResource = resourceResolver.getResource(parentPath);
        if (parentResource == null) {
            parentResource = createResourceHierarchy(parentPath);
        }
        return binaryResource(inputStream, parentResource, name, mimeType);
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
     * type is auto-detected from resource name.
     * @param inputStream Input stream for binary data
     * @param parentResource Parent resource
     * @param name Resource name for nt:resource
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String name) {
        return binaryResource(inputStream, parentResource, name, detectMimeTypeFromNames(name));
    }

    /**
     * Import binary file as nt:resource binary node into repository.
     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
     * @param inputStream Input stream for binary data
     * @param parentResource Parent resource
     * @param name Resource name for nt:resource
     * @param mimeType Mime type of binary data
     * @return Resource with binary data
     */
    public @NotNull Resource binaryResource(@NotNull InputStream inputStream, @NotNull Resource parentResource, @NotNull String name, @NotNull String mimeType) {
        try {
            Resource resource = resourceResolver.create(parentResource, name,
                    ImmutableValueMap.of(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_RESOURCE,
                            JcrConstants.JCR_DATA, inputStream,
                            JcrConstants.JCR_MIMETYPE, mimeType));
            if (autoCommit) {
                resourceResolver.commit();
            }
            return resource;
        } catch (PersistenceException ex) {
            throw new RuntimeException("Unable to create resource at " + parentResource.getPath() + "/" + name, ex);
        }
    }

    /**
     * Detected mime type from any of the given names (evaluating the file extension) using Mime Type service.
     * Fallback to application/octet-stream.
     * @param names The names from which to derive the mime type
     * @return Mime type (never null)
     */
    @SuppressWarnings("null")
    private @NotNull String detectMimeTypeFromNames(@NotNull String @NotNull ... names) {
        String mimeType = null;
        for (String name : names) {
            String fileExtension = StringUtils.substringAfterLast(name, ".");
            if (bundleContext != null && StringUtils.isNotEmpty(fileExtension)) {
                ServiceReference<MimeTypeService> ref = bundleContext.getServiceReference(MimeTypeService.class);
                if (ref != null) {
                    MimeTypeService mimeTypeService = bundleContext.getService(ref);
                    mimeType = mimeTypeService.getMimeType(fileExtension);
                    break;
                }
            }
        }
        return StringUtils.defaultString(mimeType, CONTENTTYPE_OCTET_STREAM);
    }

    /**
     * Mount a folder (file system) containing content in JSON (Sling-Inital-Content) format in repository.
     * @param mountFolderPath Root folder path to mount
     * @param parentResource Parent resource
     * @param childName Name of child resource to mount folder into
     */
    public void folderJson(@NotNull String mountFolderPath, @NotNull Resource parentResource, @NotNull String childName) {
        folderJson(new File(mountFolderPath), parentResource, childName);
    }

    /**
     * Mount a folder (file system) containing content in JSON (Sling-Inital-Content) format in repository.
     * @param mountFolderPath Root folder path to mount
     * @param destPath Path to mount folder into
     */
    public void folderJson(@NotNull String mountFolderPath, @NotNull String destPath) {
        folderJson(new File(mountFolderPath), destPath);
    }

    /**
     * Mount a folder containing content in JSON (Sling-Inital-Content) format in repository.
     * @param mountFolder Root folder to mount
     * @param parentResource Parent resource
     * @param childName Name of child resource to mount folder into
     */
    public void folderJson(@NotNull File mountFolder, @NotNull Resource parentResource, @NotNull String childName) {
        folderJson(mountFolder, parentResource.getPath() + "/" + childName);
    }

    /**
     * Mount a folder containing content in JSON (Sling-Inital-Content) format in repository.
     * @param mountFolder Root folder to mount
     * @param destPath Path to mount folder into
     */
    public void folderJson(@NotNull File mountFolder, @NotNull String destPath) {
        registerFileSystemResourceProvider(
                "provider.file", mountFolder.getAbsolutePath(),
                "provider.root", destPath,
                "provider.fs.mode", "INITIAL_CONTENT",
                "provider.initial.content.import.options", "overwrite:=true;ignoreImportProviders:=\"xml\"",
                "provider.checkinterval", 0);
    }

    /**
     * Mount a folder (file system) containing content in FileVault XML format in repository.
     * @param mountFolderPath Root folder path to mount. Path needs to point to the root folder of the content package structure.
     * @param parentResource Parent resource
     * @param childName Name of child resource of subtree path that should be mounted from FileVault XML structure
     */
    public void folderFileVaultXml(@NotNull String mountFolderPath, @NotNull Resource parentResource, @NotNull String childName) {
        folderFileVaultXml(new File(mountFolderPath), parentResource, childName);
    }

    /**
     * Mount a folder (file system) containing content in FileVault XML format in repository.
     * @param mountFolderPath Root folder path to mount. Path needs to point to the root folder of the content package structure.
     * @param destPath Subtree path that should be mounted from FileVault XML structure
     */
    public void folderFileVaultXml(@NotNull String mountFolderPath, @NotNull String destPath) {
        folderFileVaultXml(new File(mountFolderPath), destPath);
    }

    /**
     * Mount a folder containing content in FileVault XML format in repository.
     * @param mountFolder Root folder to mount. Path needs to point to the root folder of the content package structure.
     * @param parentResource Parent resource
     * @param childName Name of child resource of subtree path that should be mounted from FileVault XML structure
     */
    public void folderFileVaultXml(@NotNull File mountFolder, @NotNull Resource parentResource, @NotNull String childName) {
        folderFileVaultXml(mountFolder, parentResource.getPath() + "/" + childName);
    }

    /**
     * Mount a folder containing content in FileVault XML format in repository.
     * @param mountFolder Root folder to mount. Path needs to point to the root folder of the content package structure.
     * @param destPath Subtree path that should be mounted from FileVault XML structure
     */
    public void folderFileVaultXml(@NotNull File mountFolder, @NotNull String destPath) {
        registerFileSystemResourceProvider(
                "provider.file", mountFolder.getAbsolutePath(),
                "provider.root", destPath,
                "provider.fs.mode", "FILEVAULT_XML",
                "provider.checkinterval", 0);
    }

    /**
     * Get input stream for a resource either from classpath (preferred) or from filesystem (fallback).
     * @param classpathResourceOrFile Classpath resource URL or file path
     * @param processor Processes input stream
     */
    @SuppressWarnings({ "null", "deprecation" })
    private <T> @NotNull T processInputStreamFromClasspathOrFilesystem(@NotNull String classpathResourceOrFile, @NotNull Function<InputStream,T> processor) {
        InputStream is = ContentLoader.class.getResourceAsStream(classpathResourceOrFile);
        if (is == null) {
            try {
                is = new FileInputStream(classpathResourceOrFile);
            }
            catch (FileNotFoundException ex) {
                throw new IllegalArgumentException("Classpath resource or file not found: " + classpathResourceOrFile);
            }
        }
        try {
            return processor.apply(is);
        }
        finally {
            IOUtils.closeQuietly(is);
        }
    }

    @SuppressWarnings("null")
    private void registerFileSystemResourceProvider(Object... serviceProperties) {
        if (bundleContext == null) {
            throw new IllegalStateException("No bundle context given for content loader.");
        }
        if (isUsingMockResourceResolverFactory()) {
            throw new IllegalStateException("Loading folder content is not supported with RESOURCERESOLVER_MOCK resource resolver type. "
                    + "Use RESOURCEPROVIDER_MOCK or one of the other types.");
        }
        Dictionary<String,Object> props = MapUtil.toDictionary(serviceProperties);
        FsResourceProvider service = MockOsgi.activateInjectServices(FsResourceProvider.class, bundleContext, props);
        bundleContext.registerService(ResourceProvider.class, service, props);
    }

    private boolean isUsingMockResourceResolverFactory() {
        ServiceReference<ResourceResolverFactory> serviceReference = bundleContext.getServiceReference(ResourceResolverFactory.class);
        if (serviceReference == null) {
            throw new IllegalStateException("No resource resolver factory service present.");
        }
        try {
            ResourceResolverFactory resourceResolverFactory = bundleContext.getService(serviceReference);
            return resourceResolverFactory instanceof MockResourceResolverFactory;
        }
        finally {
            bundleContext.ungetService(serviceReference);
        }
    }

}
