/*
 * 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.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.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
     */
    @SuppressWarnings("null")
    public void folderJson(@NotNull File mountFolder, @NotNull String destPath) {
        if (bundleContext == null) {
            throw new IllegalArgumentException("No bundle context given for content loader.");
        }
        Dictionary<String, Object> serviceProperties = MapUtil.toDictionary(
                "provider.file", mountFolder.getAbsolutePath(),
                "provider.root", destPath,
                "provider.fs.mode", "INITIAL_CONTENT",
                "provider.initial.content.import.options", "overwrite:=true;ignoreImportProviders:=\"xml\"",
                "provider.checkinterval", 0);
        FsResourceProvider service = MockOsgi.activateInjectServices(FsResourceProvider.class, bundleContext, serviceProperties);
        bundleContext.registerService(ResourceProvider.class, service, serviceProperties);
    }

    /**
     * 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
     */
    @SuppressWarnings("null")
    public void folderFileVaultXml(@NotNull File mountFolder, @NotNull String destPath) {
        if (bundleContext == null) {
            throw new IllegalArgumentException("No bundle context given for content loader.");
        }
        Dictionary<String, Object> serviceProperties = MapUtil.toDictionary(
                "provider.file", mountFolder.getAbsolutePath(),
                "provider.root", destPath,
                "provider.fs.mode", "FILEVAULT_XML",
                "provider.checkinterval", 0);
        FsResourceProvider service = MockOsgi.activateInjectServices(FsResourceProvider.class, bundleContext, serviceProperties);
        bundleContext.registerService(ResourceProvider.class, service, serviceProperties);
    }

    /**
     * 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")
    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);
        }
    }

}
