/*
 * 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 SF 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.resourceresolver.impl.helper;

import java.io.Closeable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.collections4.iterators.IteratorChain;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.sling.api.resource.LoginException;
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.api.resource.SyntheticResource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.path.PathBuilder;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
import org.apache.sling.resourceresolver.impl.providers.stateful.AuthenticatedResourceProvider;
import org.apache.sling.resourceresolver.impl.providers.tree.Node;
import org.apache.sling.resourceresolver.impl.providers.tree.PathTree;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class takes a number of {@link AuthenticatedResourceProvider} objects and
 * exposes it as one such object. Provider appropriate for the given operation
 * is chosen basing on its {@link ResourceProviderInfo#getPath()} (more specific
 * first) and service ranking.
 *
 * Like a resource resolver itself, this class is not thread safe.
 */
public class ResourceResolverControl {

    private static final Logger logger = LoggerFactory.getLogger(ResourceResolverControl.class);

    private static final String[] FORBIDDEN_ATTRIBUTES = new String[] {
            ResourceResolverFactory.PASSWORD,
            ResourceProvider.AUTH_SERVICE_BUNDLE,
            ResourceResolverFactory.SUBSERVICE};

    /** Is this a resource resolver for an admin? */
    private final boolean isAdmin;

    /** The authentication info. */
    private final Map<String, Object> authenticationInfo;

    /** Resource type resource resolver (admin resolver) */
    private volatile ResourceResolver resourceTypeResourceResolver;

    /** Flag for handling multiple calls to close. */
    private final AtomicBoolean isClosed = new AtomicBoolean(false);

    private final ResourceProviderStorageProvider resourceProviderTracker;

    private final Map<ResourceProviderHandler, Object> authenticatedProviders;

    /**
     * Create a new resource resolver context.
     */
    public ResourceResolverControl(final boolean isAdmin,
            final Map<String, Object> authenticationInfo,
            final ResourceProviderStorageProvider resourceProviderTracker) {
        this.authenticatedProviders = new IdentityHashMap<>();
        this.authenticationInfo = authenticationInfo;
        this.isAdmin = isAdmin;
        this.resourceProviderTracker = resourceProviderTracker;
    }

    /**
     * Is this an admin resource resolver?
     * @return{@code true} if it is an admin resource resolver
     */
    public boolean isAdmin() {
        return isAdmin;
    }

    /**
     * The authentication info
     * @return The map with the auth info
     */
    public Map<String, Object> getAuthenticationInfo() {
        return this.authenticationInfo;
    }

    /**
     * Is this already closed?
     * @return {@code true} if it is closed.
     */
    public boolean isClosed() {
        return this.isClosed.get();
    }

    /**
     * Logs out from all providers.
     */
    private void logout() {
        for(final Map.Entry<ResourceProviderHandler, Object> entry : this.authenticatedProviders.entrySet()) {
            try {
                final ResourceProvider<Object> rp = entry.getKey().getResourceProvider();
                if ( rp != null ) {
                    rp.logout(entry.getValue());
                } else if ( entry.getValue() instanceof Closeable ) {
                    ((Closeable)entry.getValue()).close();
                }
            } catch ( final Throwable t ) {
                // we ignore everything from there to not stop this thread
            }
        }
        this.authenticatedProviders.clear();
    }

    /**
     * Refreshes all refreshable providers as well as the resolver used for resource types.
     */
    public void refresh(@NotNull final ResourceResolverContext context) {
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedRefreshable()) {
            p.refresh();
        }
        if (this.resourceTypeResourceResolver != null) {
            this.resourceTypeResourceResolver.refresh();
        }
    }

    /**
     * Returns {@code true} if all providers are live.
     */
    public boolean isLive(@NotNull final ResourceResolverContext context) {
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllAuthenticated()) {
            if (!p.isLive()) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns parent from the most appropriate resource provider accepting the
     * given children.
     *
     * In some cases the {@link SyntheticResource} can be returned if no
     * resource provider returns parent for this child. See
     * {@link #getResource(String, Resource, Map, boolean)} for more details
     */
    public Resource getParent(@NotNull final ResourceResolverContext context, @NotNull final String parentPath, @NotNull final Resource child) {
        final AuthenticatedResourceProvider childProvider = getBestMatchingProvider(context, child.getPath());
        final AuthenticatedResourceProvider parentProvider = getBestMatchingProvider(context, parentPath);
        if ( parentProvider != null ) {
            final Resource parentCandidate;
            if ( childProvider == parentProvider ) {
                parentCandidate = parentProvider.getParent(child);
            } else {
                parentCandidate = parentProvider.getResource(parentPath, null, null);
            }
            if (parentCandidate != null) {
                return parentCandidate;
            }
        }

        if (isIntermediatePath(parentPath)) {
            return new SyntheticResource(context.getResourceResolver(), parentPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC);
        }
        return null;
    }

    /**
     * Returns resource from the most appropriate resource provider.
     * <br/><br/>
     * If there's no such provider and the path is a part of some resource
     * provider path, then the {@link SyntheticResource} will be returned. For
     * instance, if we have resource provider under
     * {@code /libs/sling/servlet/default/GET.servlet} and no resource provider
     * returns a resource for {@code /libs/sling/servlet/default}, then the
     * {@link SyntheticResource} will be returned to provide a consistent
     * resource tree.
     * <br/><br/>
     * The same behaviour occurs in {@link #getParent(Resource)} and
     * {@link #listChildren(Resource)}.
     */
    public Resource getResource(final ResourceResolverContext context,
            String path, Resource parent, Map<String, String> parameters,
            boolean isResolve) {
        if (path == null || path.length() == 0 || path.charAt(0) != '/') {
            logger.debug("Not absolute {}", path);
            return null; // path must be absolute
        }

        final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, path);
        if ( provider != null ) {
            final Resource resourceCandidate = provider.getResource(path, parent, parameters);
            if (resourceCandidate != null) {
                return resourceCandidate;
            }
        }

        // query: /libs/sling/servlet/default
        // resource Provider: libs/sling/servlet/default/GET.servlet
        // list will match libs, sling, servlet, default
        // and there will be no resource provider at the end
        // SLING-3482 : this is only done for getResource but not resolve
        //              as it is important e.g. for servlet resolution
        //              to get the parent resource for resource traversal.
        if (!isResolve && isIntermediatePath(path)) {
            logger.debug("Resolved Synthetic {}", path);
            return new SyntheticResource(context.getResourceResolver(), path, ResourceProvider.RESOURCE_TYPE_SYNTHETIC);
        }
        logger.debug("Resource null {} ", path);
        return null;
    }

    private boolean isIntermediatePath(final String fullPath) {
        return getResourceProviderStorage().getTree().getNode(fullPath) != null;
    }

    /**
     * This method asks all matching resource providers for the children iterators,
     * merges them, adds {@link SyntheticResource}s (see
     * {@link #getResource(String, Resource, Map, boolean)} for more details),
     * filters out the duplicates and returns the resulting iterator. All
     * transformations are done lazily, during the {@link Iterator#hasNext()}
     * invocation on the result.
     */
    @SuppressWarnings("unchecked")
    public Iterator<Resource> listChildren(final ResourceResolverContext context, final Resource parent) {
        final String parentPath = parent.getPath();

        // 3 sources are combined: children of the provider which owns 'parent',
        // providers which are directly mounted at a child path,
        // synthetic resources for providers mounted at a lower level

        // children of the 'parent' provider
        Iterator<Resource> realChildren = null;
        final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, parentPath);
        if ( provider != null ) {
            realChildren = provider.listChildren(parent);
        }

        final Set<String> visitedNames = new HashSet<>();

        IteratorChain chain = new IteratorChain();
        if ( realChildren != null ) {
            chain.addIterator(realChildren);
        }

        // synthetic and providers are done in one loop
        final Node<ResourceProviderHandler> node = getResourceProviderStorage().getTree().getNode(parent.getPath());
        if (node != null) {
            final List<Resource> syntheticList = new ArrayList<>();
            final List<Resource> providerList = new ArrayList<>();

            for (final Entry<String, Node<ResourceProviderHandler>> entry : node.getChildren().entrySet()) {
                final String name = entry.getKey();
                final ResourceProviderHandler handler = entry.getValue().getValue();
                PathBuilder pathBuilder = new PathBuilder(parent.getPath());
                pathBuilder.append(name);
                final String childPath = pathBuilder.toString();
                if (handler == null) {
                    syntheticList.add(new SyntheticResource(context.getResourceResolver(), childPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC));
                } else {
                    Resource rsrc = null;
                    try {
                        final AuthenticatedResourceProvider rp = context.getProviderManager().getOrCreateProvider(handler, this);
                        rsrc = rp == null ? null : rp.getResource(childPath, parent, null);
                    } catch ( final LoginException ignore) {
                        // ignore
                    }
                    if ( rsrc != null ) {
                        providerList.add(rsrc);
                    } else {
                        // if there is a child provider underneath, we need to create a synthetic resource
                        // otherwise we need to make sure that no one else is providing this child
                        if ( entry.getValue().getChildren().isEmpty() ) {
                            syntheticList.add(new SyntheticResource(context.getResourceResolver(), childPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC));
                        } else {
                            visitedNames.add(name);
                        }
                    }
                }
            }
            if ( !providerList.isEmpty() ) {
                chain.addIterator(providerList.iterator());
            }
            if ( !syntheticList.isEmpty() ) {
                chain.addIterator(syntheticList.iterator());
            }
        }
        if ( chain.size() == 0 ) {
            return Collections.EMPTY_LIST.iterator();
        }
        return new UniqueResourceIterator(visitedNames, chain);
    }

    /**
     * Returns the union of all attribute names.
     */
    public Collection<String> getAttributeNames(final ResourceResolverContext context) {
        final Set<String> names = new LinkedHashSet<>();
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAttributableHandlers(), this)) {
            p.getAttributeNames(names);
        }
        if ( this.authenticationInfo != null ) {
            names.addAll(authenticationInfo.keySet());
        }
        for(final String key : FORBIDDEN_ATTRIBUTES) {
            names.remove(key);
        }
        return names;
    }

    /**
     * Returns the first non-null result of the
     * {@link AuthenticatedResourceProvider#getAttribute(String)} invocation on
     * the providers.
     */
    public Object getAttribute(final ResourceResolverContext context, final String name) {
        for(final String key : FORBIDDEN_ATTRIBUTES) {
            if (key.equals(name)) {
                return null;
            }
        }
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAttributableHandlers(), this)) {
            final Object attribute = p.getAttribute(name);
            if (attribute != null) {
                return attribute;
            }
        }
        return this.authenticationInfo != null ? this.authenticationInfo.get(name) :null;
    }

    /**
     * Create a resource.
     *
     * @throws UnsupportedOperationException
     *             If creation is not allowed/possible
     * @throws PersistenceException
     *             If creation fails
     * @return The new resource
     */
    public Resource create(final ResourceResolverContext context,
            final String path, final Map<String, Object> properties)
                    throws PersistenceException {
        final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
        if ( provider != null ) {
            final Resource creationResultResource = provider.create(context.getResourceResolver(), path, properties);
            if (creationResultResource != null) {
                return creationResultResource;
            }
        }
        throw new UnsupportedOperationException("create '" + ResourceUtil.getName(path) + "' at " + ResourceUtil.getParent(path));
    }

    /**
     * Delete the resource. Iterate over all modifiable ResourceProviders
     * giving each an opportunity to delete the resource if they are able.
     *
     * @throws NullPointerException
     *             if resource is null
     * @throws UnsupportedOperationException
     *             If deletion is not allowed/possible
     * @throws PersistenceException
     *             If deletion fails
     */
    public void delete(final ResourceResolverContext context, final Resource resource) throws PersistenceException {
        final String path = resource.getPath();
        final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
        if ( provider != null ) {
            provider.delete(resource);
            return;
        }
        throw new UnsupportedOperationException("delete at '" + path + "'");
    }

    /**
     * Revert changes on all modifiable ResourceProviders.
     */
    public void revert(final ResourceResolverContext context) {
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
            p.revert();
        }
    }

    /**
     * Commit changes on all modifiable ResourceProviders.
     */
    public void commit(final ResourceResolverContext context) throws PersistenceException {
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
            p.commit();
        }
    }

    /**
     * Check if any modifiable ResourceProvider has uncommited changes.
     */
    public boolean hasChanges(final ResourceResolverContext context) {
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
            if (p.hasChanges()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return the union of query languages supported by the providers.
     */
    public String[] getSupportedLanguages(final ResourceResolverContext context) {
        final Set<String> supportedLanguages = new LinkedHashSet<>();
        for (AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getLanguageQueryableHandlers(), this)) {
            supportedLanguages.addAll(Arrays.asList(p.getSupportedLanguages()));
        }
        return supportedLanguages.toArray(new String[supportedLanguages.size()]);
    }

    /**
     * Queries all resource providers and combines the results.
     */
    public Iterator<Resource> findResources(final ResourceResolverContext context,
            final String query, final String language) {
        final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
        final List<Iterator<Resource>> iterators = new ArrayList<>(queryableRP.size());
        for (AuthenticatedResourceProvider p : queryableRP) {
            iterators.add(p.findResources(query, language));
        }
        return new ChainedIterator<>(iterators.iterator());
    }

    private List<AuthenticatedResourceProvider> getQueryableProviders(
            final ResourceResolverContext context,
            final String language) {
        final List<AuthenticatedResourceProvider> queryableProviders = new ArrayList<>();
        for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getLanguageQueryableHandlers(), this)) {
            if (ArrayUtils.contains(p.getSupportedLanguages(), language)) {
                queryableProviders.add(p);
            }
        }
        return queryableProviders;
    }

    /**
     * Queries all resource providers and combines the results.
     */
    public Iterator<Map<String, Object>> queryResources(final ResourceResolverContext context,
            final String query, final String language) {
        final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
        final List<Iterator<Map<String, Object>>> iterators = new ArrayList<>(queryableRP.size());
        for (AuthenticatedResourceProvider p : queryableRP) {
            iterators.add(p.queryResources(query, language));
        }
        return new ChainedIterator<>(iterators.iterator());
    }

    /**
     * Returns the first non-null result of the adaptTo() method invoked on the
     * providers.
     */
    @SuppressWarnings("unchecked")
    public <AdapterType> AdapterType adaptTo(final ResourceResolverContext context, Class<AdapterType> type) {
        for (AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAdaptableHandlers(), this)) {
            final Object adaptee = p.adaptTo(type);
            if (adaptee != null) {
                return (AdapterType) adaptee;
            }
        }
        return null;
    }

    private AuthenticatedResourceProvider checkExistence(final ResourceResolverContext context, final String path,
            final String type) throws PersistenceException {
        final Node<ResourceProviderHandler> node = getResourceProviderStorage().getTree().getBestMatchingNode(path);
        if (node == null) {
            throw new PersistenceException(type.concat(" resource does not exist."), null, path, null);
        }
        AuthenticatedResourceProvider provider = null;
        try {
            provider = context.getProviderManager().getOrCreateProvider(node.getValue(), this);
        } catch (LoginException e) {
            // ignore
        }
        if (provider == null) {
            throw new PersistenceException(type.concat(" resource does not exist."), null, path, null);
        }
        final Resource rsrc = provider.getResource(path, null, null);
        if (rsrc == null) {
            throw new PersistenceException(type.concat(" resource does not exist."), null, path, null);
        }
        return provider;
    }

    public AuthenticatedResourceProvider checkSourceAndDest(final ResourceResolverContext context,
            final String srcAbsPath, final String destAbsPath) throws PersistenceException {
        // check source
        final AuthenticatedResourceProvider srcProvider = checkExistence(context, srcAbsPath, "Source");
        // check destination
        final AuthenticatedResourceProvider destProvider = checkExistence(context, destAbsPath, "Destination");

        // check for sub providers of src and dest
        if (srcProvider == destProvider) {
            final PathTree<ResourceProviderHandler> providerTree = getResourceProviderStorage().getTree();
            final boolean sourceHasProvider = hasSubProvider(context, providerTree.getNode(srcAbsPath));
            final boolean destHasProvider = hasSubProvider(context, providerTree.getNode(destAbsPath));
            if (!(sourceHasProvider || destHasProvider)) {
                return srcProvider;
            }
        }
        return null;
    }

    private boolean hasSubProvider(ResourceResolverContext context, Node<ResourceProviderHandler> node) {
        if (node != null) {
            for (final Node<ResourceProviderHandler> childNode : node.getChildren().values()) {
                final ResourceProviderHandler handler = childNode.getValue();
                if (handler != null) {
                    try {
                        context.getProviderManager().getOrCreateProvider(handler, this);
                        return true;
                    } catch (final LoginException ignore) {
                        // ignore
                    }
                }
                if (hasSubProvider(context, childNode)) {
                    return true;
                }
            }
        }

        return false;
    }

    private void copy(final ResourceResolverContext context, final Resource src, final String dstPath, final List<Resource> newNodes) throws PersistenceException {
        final ValueMap vm = src.getValueMap();
        final String createPath = new PathBuilder(dstPath).append(src.getName()).toString();
        newNodes.add(this.create(context, createPath, vm));
        for(final Resource c : src.getChildren()) {
            copy(context, c, createPath, newNodes);
        }
    }

    /**
     * Tries to find a resource provider accepting both paths and invokes
     * {@link AuthenticatedResourceProvider#copy(String, String)} method on it.
     * Returns false if there's no such provider.
     */
    public Resource copy(final ResourceResolverContext context,
            final String srcAbsPath, final String destAbsPath) throws PersistenceException {
        final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
        if ( optimizedSourceProvider != null && optimizedSourceProvider.copy(srcAbsPath, destAbsPath) ) {
            return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
        }

        final Resource srcResource = this.getResource(context, srcAbsPath, null, null, false);
        final List<Resource> newResources = new ArrayList<>();
        boolean rollback = true;
        try {
            this.copy(context, srcResource, destAbsPath, newResources);
            rollback = false;
            return newResources.get(0);
        } finally {
            if ( rollback ) {
                for(final Resource rsrc : newResources) {
                    this.delete(context, rsrc);
                }
            }
        }
    }

    /**
     * Tries to find a resource provider accepting both paths and invokes
     * {@link AuthenticatedResourceProvider#move(String, String)} method on it.
     * Returns false if there's no such provider.
     */
    public Resource move(final ResourceResolverContext context,
            String srcAbsPath, String destAbsPath) throws PersistenceException {
        final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
        if ( optimizedSourceProvider != null && optimizedSourceProvider.move(srcAbsPath, destAbsPath) ) {
            return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
        }
        final Resource srcResource = this.getResource(context, srcAbsPath, null, null, false);
        final List<Resource> newResources = new ArrayList<>();
        boolean rollback = true;
        try {
            this.copy(context, srcResource, destAbsPath, newResources);
            this.delete(context, srcResource);
            rollback = false;
            return newResources.get(0);
        } finally {
            if ( rollback ) {
                for(final Resource rsrc : newResources) {
                    this.delete(context, rsrc);
                }
            }
        }
    }

    public ResourceProviderStorage getResourceProviderStorage() {
        return this.resourceProviderTracker.getResourceProviderStorage();
    }

    /**
     * @param path
     * @return
     */
    private @Nullable AuthenticatedResourceProvider getBestMatchingProvider(final ResourceResolverContext context,
            final String path) {
        try {
            final Node<ResourceProviderHandler> node = resourceProviderTracker.getResourceProviderStorage().getTree().getBestMatchingNode(path);
            return node == null ? null : context.getProviderManager().getOrCreateProvider(node.getValue(), this);
        } catch ( final LoginException le ) {
            // ignore
            return null;
        }
    }

    /**
     * @param path
     * @return The modifiable provider or {@code null}
     */
    private @Nullable AuthenticatedResourceProvider getBestMatchingModifiableProvider(
            final ResourceResolverContext context,
            final String path)  {
        final Node<ResourceProviderHandler> node = resourceProviderTracker.getResourceProviderStorage().getTree().getBestMatchingNode(path);
        if ( node != null && node.getValue().getInfo().isModifiable() ) {
            try {
                return context.getProviderManager().getOrCreateProvider(node.getValue(), this);
            } catch ( final LoginException le ) {
                // ignore
                return null;
            }
        }
        return null;
    }


    /**
     * Close all dynamic resource providers.
     */
    public void close() {
        if (this.isClosed.compareAndSet(false, true)) {
            this.logout();
            if ( this.resourceTypeResourceResolver != null ) {
                try {
                    this.resourceTypeResourceResolver.close();
                } catch ( final Throwable t) {
                    // the resolver (or the underlying provider) might already be terminated (bundle stopped etc.)
                    // so we ignore anything from here
                }
                this.resourceTypeResourceResolver = null;
            }
        }
    }

    private ResourceResolver getResourceTypeResourceResolver(
            final ResourceResolverFactory factory,
            final ResourceResolver resolver) {
        if ( this.isAdmin ) {
            return resolver;
        } else {
            if ( this.resourceTypeResourceResolver == null ) {
                try {
                    // make sure we're getting the resourceTypeResourceResolver on behalf of
                    // the resourceresolver bundle
                    final Bundle bundle = FrameworkUtil.getBundle(ResourceResolverControl.class);
                    final Map<String, Object> authenticationInfo = new HashMap<>();
                    authenticationInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, bundle);
                    authenticationInfo.put(ResourceResolverFactory.SUBSERVICE, "hierarchy");
                    this.resourceTypeResourceResolver = factory.getServiceResourceResolver(authenticationInfo);
                } catch (final LoginException e) {
                    throw new IllegalStateException("Failed to create resource-type ResourceResolver", e);
                }
            }
            return this.resourceTypeResourceResolver;
        }
    }

    /**
     * Get the parent resource type
     *
     * @see org.apache.sling.api.resource.ResourceResolver#getParentResourceType(java.lang.String)
     */
    public String getParentResourceType(
            final ResourceResolverFactory factory,
            final ResourceResolver resolver,
            final String resourceType) {
        // normalize resource type to a path string
        final String rtPath = (resourceType == null ? null : ResourceUtil.resourceTypeToPath(resourceType));
        // get the resource type resource and check its super type
        String resourceSuperType = null;

        if ( rtPath != null ) {
            ResourceResolver adminResolver = this.getResourceTypeResourceResolver(factory, resolver);
            if ( adminResolver != null ) {
                final Resource rtResource = adminResolver.getResource(rtPath);
                if (rtResource != null) {
                    resourceSuperType = rtResource.getResourceSuperType();
                }
            }
        }
        return resourceSuperType;
    }

    /**
     * Returns {@link #getProperty(Resource, String, Class) getProperty(res,
     * propName, String.class)}
     *
     * @param res The resource to access the property from
     * @param propName The name of the property to access
     * @return The property as a {@code String} or {@code null} if the property
     *         does not exist or cannot be converted into a {@code String}
     */
    public static String getProperty(final Resource res, final String propName) {
        return getProperty(res, propName, String.class);
    }

    /**
     * Returns the value of the name property of the resource converted to the
     * requested {@code type}.
     * <p>
     * If the resource itself does not have the property, the property is looked
     * up in the {@code jcr:content} child node. This access is done through the
     * same {@code ValueMap} as is used to access the property directly. This
     * generally only works for JCR based {@code ValueMap} instances which
     * provide access to relative path property names. This may not work in non
     * JCR {@code ValueMap}, however in non JCR envs there is usually no
     * "jcr:content" child node anyway
     *
     * @param res The resource to access the property from
     * @param propName The name of the property to access
     * @param type The type into which to convert the property
     * @return The property converted to the requested {@code type} or
     *         {@code null} if the property does not exist or cannot be
     *         converted into the requested {@code type}
     */
    public static <Type> Type getProperty(final Resource res, final String propName, final Class<Type> type) {

        // check the property in the resource itself
        final ValueMap props = res.adaptTo(ValueMap.class);
        if (props != null) {
            Type prop = props.get(propName, type);
            if (prop != null) {
                return prop;
            }
            // otherwise, check it in the jcr:content child resource
            // This is a special case checking for JCR based resources
            // we directly use the deep resolution of properties of the
            // JCR value map implementation - this does not work
            // in non JCR environments, however in non JCR envs there
            // is usually no "jcr:content" child node anyway
            prop = props.get("jcr:content/" + propName, type);
            return prop;
        }

        return null;
    }

    public void registerAuthenticatedProvider(@NotNull ResourceProviderHandler handler,
            @Nullable Object providerState) {
        this.authenticatedProviders.put(handler, providerState);
    }

    public void clearAuthenticatedProviders() {
        this.authenticatedProviders.clear();
    }
}
