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

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.jetbrains.annotations.NotNull;

import org.apache.commons.collections4.BidiMap;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.resourceresolver.impl.console.ResourceResolverWebConsolePlugin;
import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider;
import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
import org.apache.sling.resourceresolver.impl.mapping.MapEntriesHandler;
import org.apache.sling.resourceresolver.impl.mapping.Mapping;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>CommonResourceResolverFactoryImpl</code> is a singleton
 * implementing the shared/common functionality of all resource
 * resolver factories.
 */
public class CommonResourceResolverFactoryImpl implements ResourceResolverFactory, MapConfigurationProvider {

    private static final Logger LOG = LoggerFactory.getLogger(CommonResourceResolverFactoryImpl.class);

    private static final String[] FORBIDDEN_AUTH_INFO_KEYS = {ResourceProvider.AUTH_CLONE};

    /** Helper for the resource resolver. */
    private MapEntriesHandler mapEntries = MapEntriesHandler.EMPTY;

    /** The web console plugin. */
    private ResourceResolverWebConsolePlugin plugin;

    /** The activator */
    private final ResourceResolverFactoryActivator activator;

    /**
     * Thread local holding the resource resolver stack
     */
    private ThreadLocal<Stack<WeakReference<ResourceResolver>>> resolverStackHolder = new ThreadLocal<>();

    /** Flag indicating whether this factory is still active. */
    private final AtomicBoolean isActive = new AtomicBoolean(true);

    /** The reference queue to handle disposing of resource resolver instances. */
    private final ReferenceQueue<ResourceResolver> resolverReferenceQueue = new ReferenceQueue<>();

    /** Map of the ResourceResolverControl's hash code to the references to open resource resolver instances. */
    private final Map<Integer, ResolverReference> refs = new ConcurrentHashMap<>();

    /** Background thread handling disposing of resource resolver instances. */
    private final Thread refQueueThread;

    private boolean logUnclosedResolvers;

    private final Object optionalNamespaceMangler;


    /**
     * Create a new common resource resolver factory.
     */
    public CommonResourceResolverFactoryImpl(final ResourceResolverFactoryActivator activator) {
        this.activator = activator;
        this.logUnclosedResolvers = activator.isLogUnclosedResourceResolvers();
        this.refQueueThread = new Thread("Apache Sling Resource Resolver Finalizer Thread") {

            @Override
            public void run() {
                while (isLive()) {
                    try {
                        final ResolverReference ref = (ResolverReference) resolverReferenceQueue.remove();
                        ref.close();
                    } catch ( final InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        };
        this.refQueueThread.setDaemon(true);
        this.refQueueThread.start();

        // try create namespace mangler
        Object mangler = null;
        if ( this.isMangleNamespacePrefixes() ) {
            try {
                mangler = new JcrNamespaceMangler();
            } catch ( final Throwable t) {
                LOG.info("Unable to create JCR namespace mangler: {}", t.getMessage());
            }
        }
        this.optionalNamespaceMangler = mangler;
    }

    // ---------- Resource Resolver Factory ------------------------------------
    
    /**
     * Sanitize the authentication info passed from external code. This method will always make a defensive
     * copy of the argument, also making sure that the copy is mutable. Nulls are turned into empty (mutable) maps.
     * Keys that are used to communicate with resource providers are removed from the copy, and optionally
     * other keys can be removed as well.
     * @param authenticationInfo The authentication info to sanitize, may be null.
     * @param extraForbiddenKeys Keys that should be removed from the returned copy.
     * @return A sanitized mutable map.
     */
    @NotNull
    static Map<String, Object> sanitizeAuthenticationInfo(Map<String, Object> authenticationInfo, String... extraForbiddenKeys) {
        if (authenticationInfo == null) {
            // nothing to sanitize, just return an empty mutable map
            return new HashMap<>();
        } else {
            Map<String, Object> sanitized = new HashMap<>(authenticationInfo);
            for (String key : FORBIDDEN_AUTH_INFO_KEYS) {
                sanitized.remove(key);
            }
            for (String key : extraForbiddenKeys) {
                sanitized.remove(key);
            }
            return sanitized;
        }
    }

    /**
     * @see org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)
     */
    @NotNull
    @Override
    public ResourceResolver getAdministrativeResourceResolver(final Map<String, Object> passedAuthenticationInfo)
    throws LoginException {
        checkIsLive();

        // make sure there is no leaking of service info props
        // (but the bundle info is passed on as we need it downstream)
        final Map<String, Object> authenticationInfo = sanitizeAuthenticationInfo(passedAuthenticationInfo, SUBSERVICE);
        authenticationInfo.put(ResourceProvider.AUTH_ADMIN, Boolean.TRUE);

        return getResourceResolverInternal(authenticationInfo, true);
    }

    /**
     * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)
     */
    @NotNull
    @Override
    public ResourceResolver getResourceResolver(final Map<String, Object> passedAuthenticationInfo)
    throws LoginException {
        checkIsLive();

        // make sure there is no leaking of service bundle and info props
        final Map<String, Object> authenticationInfo = sanitizeAuthenticationInfo(passedAuthenticationInfo, ResourceProvider.AUTH_SERVICE_BUNDLE, SUBSERVICE);

        final ResourceResolver result = getResourceResolverInternal(authenticationInfo, false);
        Stack<WeakReference<ResourceResolver>> resolverStack = resolverStackHolder.get();
        if ( resolverStack == null ) {
            resolverStack = new Stack<>();
            resolverStackHolder.set(resolverStack);
        }
        resolverStack.push(new WeakReference<>(result));
        return result;
    }


    /**
     * @see org.apache.sling.api.resource.ResourceResolverFactory#getThreadResourceResolver()
     */
    @Override
    public ResourceResolver getThreadResourceResolver() {
        if (!isLive()) {
            return null;
        }

        ResourceResolver result = null;
        final Stack<WeakReference<ResourceResolver>> resolverStack = resolverStackHolder.get();
        if ( resolverStack != null) {
            while ( result == null && !resolverStack.isEmpty() ) {
                result = resolverStack.peek().get();
                if ( result == null ) {
                    resolverStack.pop();
                }
            }
        }
        return result;
    }

    // ---------- Implementation helpers --------------------------------------

    /**
     * Inform about a new resource resolver instance.
     * We create a weak reference to be able to close the resolver if close on the
     * resource resolver is never called.
     * @param resolver The resource resolver
     * @param ctrl The resource resolver control
     */
    public void register(final ResourceResolver resolver,
            final ResourceResolverControl ctrl) {
        // create new weak reference
        refs.put(ctrl.hashCode(), new ResolverReference(resolver, this.resolverReferenceQueue, ctrl, this));
    }

    /**
     * Inform about a closed resource resolver.
     * Make sure to remove it from the current thread context.
     * @param resourceResolverImpl The resource resolver
     * @param ctrl The resource resolver control
     */
    public void unregister(final ResourceResolver resourceResolverImpl,
            final ResourceResolverControl ctrl) {
        unregisterControl(ctrl);

        // on shutdown, the factory might already be closed before the resolvers close
        // therefore we have to check for null
        final ThreadLocal<Stack<WeakReference<ResourceResolver>>> tl = resolverStackHolder;
        if ( tl != null ) {
            final Stack<WeakReference<ResourceResolver>> resolverStack = tl.get();
            if ( resolverStack != null ) {
                final Iterator<WeakReference<ResourceResolver>> i = resolverStack.iterator();
                while ( i.hasNext() ) {
                    final WeakReference<ResourceResolver> ref = i.next();
                    if ( ref.get() == null || ref.get() == resourceResolverImpl ) {
                        i.remove();
                    }
                }
                if ( resolverStack.isEmpty() ) {
                    tl.remove();
                }
            }
        }
    }

    /**
     * Create a new ResourceResolver
     * @param authenticationInfo The authentication map
     * @param isAdmin is an administrative resolver requested?
     * @return A resource resolver
     * @throws LoginException if login to any of the required resource providers fails.
     */
    ResourceResolver getResourceResolverInternal(final Map<String, Object> authenticationInfo,
                                                        final boolean isAdmin)
            throws LoginException {
        checkIsLive();

        return new ResourceResolverImpl(this, isAdmin, authenticationInfo);
    }

    /**
     * Close a resource resolver control and remove its corresponding
     * resolver reference from the map of weak references.
     *
     * @param ctrl The resource resolver control
     * @return true if the control was closed, false it had been closed before.
     */
    private boolean unregisterControl(final ResourceResolverControl ctrl) {
        // remove reference from the set of weak references and clear
        final ResolverReference reference = refs.remove(ctrl.hashCode());
        if (reference != null) {
            reference.clear();
        }
        final boolean doCloseControl = !ctrl.isClosed();
        if (doCloseControl) {
            ctrl.close();
        }
        return doCloseControl;
    }

    private void checkIsLive() throws LoginException {
        if ( !isLive() ) {
            throw new LoginException("ResourceResolverFactory is deactivated.");
        }
    }

    public MapEntriesHandler getMapEntries() {
        return mapEntries;
    }

    /** Activates this component */
    protected void activate(final BundleContext bundleContext) {
        final Logger logger = LoggerFactory.getLogger(getClass());
        try {
            plugin = new ResourceResolverWebConsolePlugin(bundleContext, this, this.activator.getRuntimeService());
        } catch (final Throwable ignore) {
            // an exception here probably means the web console plugin is not
            // available
            logger.debug("activate: unable to setup web console plugin.", ignore);
        }
        // set up the map entries from configuration
        try {
            mapEntries = new MapEntries(this, bundleContext, this.activator.getEventAdmin(), this.activator.getStringInterpolationProvider());
        } catch (final Exception e) {
            logger.error("activate: Cannot access repository, failed setting up Mapping Support", e);
        }
    }

    /**
     * Deactivates this component
     */
    protected void deactivate() {
        if (!isActive.compareAndSet(true, false)) {
            return;
        }
        this.refQueueThread.interrupt();

        if (plugin != null) {
            plugin.dispose();
            plugin = null;
        }

        if (mapEntries instanceof MapEntries ) {
            ((MapEntries)mapEntries).dispose();
            mapEntries = MapEntries.EMPTY;
        }
        resolverStackHolder = null;

        // copy and clear map before closing the remaining references
        final Collection<ResolverReference> references = new ArrayList<>(refs.values());
        refs.clear();
        for(final ResolverReference ref : references) {
            ref.close();
        }
    }

    public ResourceDecoratorTracker getResourceDecoratorTracker() {
        return this.activator.getResourceDecoratorTracker();
    }

    @Override
    public List<String> getSearchPath() {
        return this.activator.getSearchPath();
    }

    public boolean isMangleNamespacePrefixes() {
        return this.activator.isMangleNamespacePrefixes();
    }

    public Object getNamespaceMangler() {
        return this.optionalNamespaceMangler;
    }

    @Override
    public String getMapRoot() {
        return this.activator.getMapRoot();
    }

    @Override
    public boolean isMapConfiguration(String path) {
        return this.activator.isMapConfiguration(path);
    }

    @Override
    public Mapping[] getMappings() {
        return this.activator.getMappings();
    }

    @Override
    public BidiMap getVirtualURLMap() {
        return this.activator.getVirtualURLMap();
    }

    @Override
    public int getDefaultVanityPathRedirectStatus() {
        return this.activator.getDefaultVanityPathRedirectStatus();
    }

    /**
     * get's the ServiceTracker of the ResourceAccessSecurity service
     */
    public ResourceAccessSecurityTracker getResourceAccessSecurityTracker () {
        return this.activator.getResourceAccessSecurityTracker();
    }

    @NotNull
    @Override
    public ResourceResolver getServiceResourceResolver(
            final Map<String, Object> passedAuthenticationInfo) throws LoginException {
        checkIsLive();

        Map<String, Object> authenticationInfo = sanitizeAuthenticationInfo(passedAuthenticationInfo);
        return getResourceResolverInternal(authenticationInfo, false);
    }

    @Override
    public boolean isVanityPathEnabled() {
        return this.activator.isVanityPathEnabled();
    }

    @Override
    public long getMaxCachedVanityPathEntries() {
        return this.activator.getMaxCachedVanityPathEntries();
    }

    @Override
    public boolean isMaxCachedVanityPathEntriesStartup() {
        return this.activator.isMaxCachedVanityPathEntriesStartup();
    }

    @Override
    public int getVanityBloomFilterMaxBytes() {
        return this.activator.getVanityBloomFilterMaxBytes();
    }

    @Override
    public boolean isOptimizeAliasResolutionEnabled() {
        return this.activator.isOptimizeAliasResolutionEnabled();
    }

    @Override
    public boolean hasVanityPathPrecedence() {
        return this.activator.hasVanityPathPrecedence();
    }

    @Override
    public Path[] getObservationPaths() {
        return this.activator.getObservationPaths();
    }

    @Override
    public List<VanityPathConfig> getVanityPathConfig() {
        final String[] includes = this.activator.getVanityPathWhiteList();
        final String[] excludes = this.activator.getVanityPathBlackList();
        if ( includes == null && excludes == null ) {
            return null;
        }
        final List<VanityPathConfig> configs = new ArrayList<>();
        if ( includes != null ) {
            for(final String val : includes) {
                configs.add(new VanityPathConfig(val, false));
            }
        }
        if ( excludes != null ) {
            for(final String val : excludes) {
                configs.add(new VanityPathConfig(val, true));
            }
        }
        Collections.sort(configs);
        return configs;
    }

    /**
     * Is this factory still alive?
     */
    public boolean isLive() {
        return this.isActive.get();
    }

    public boolean shouldLogResourceResolverClosing() {
        return activator.shouldLogResourceResolverClosing();
    }

    public ResourceProviderTracker getResourceProviderTracker() {
        return activator.getResourceProviderTracker();
    }

    @Override
    public Map<String, Object> getServiceUserAuthenticationInfo(final String subServiceName)
    throws LoginException {
        // get an administrative resource resolver
        // Ensure a mapped user name or principal names: If no user/principal name(s)
        // is/are defined for a bundle
        // acting as a service, the user may be null. We can decide whether
        // this should yield guest access or no access at all. For now
        // no access is granted if there is no service user defined for
        // the bundle.
    	final Bundle bundle = this.activator.getBundleContext().getBundle();

        ServiceUserMapper mapper = this.activator.getServiceUserMapper();
        final Iterable<String> principalNames = mapper.getServicePrincipalNames(bundle, subServiceName);
        final String userName = (principalNames == null) ? mapper.getServiceUserID(bundle, subServiceName) : null;
        if (principalNames == null && userName == null) {
            throw new LoginException("Cannot derive user name or principal names for bundle "
                            + bundle + " and sub service " + subServiceName);
        }

        final Map<String, Object> authenticationInfo = new HashMap<>();
        // ensure proper user name and service bundle
        authenticationInfo.put(ResourceResolverFactory.SUBSERVICE, subServiceName);
        authenticationInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, bundle);
        if (userName != null) {
            authenticationInfo.put(ResourceResolverFactory.USER, userName);
        }

        return authenticationInfo;
    }

    /**
     * Extension of a weak reference to be able to get the control object
     * that is used for cleaning up.
     */
    private static final class ResolverReference extends WeakReference<ResourceResolver> {

        private final ResourceResolverControl control;

        private final Exception openingException;

        private final CommonResourceResolverFactoryImpl factory;

        ResolverReference(final ResourceResolver referent,
                          final ReferenceQueue<? super ResourceResolver> q,
                          final ResourceResolverControl ctrl,
                          final CommonResourceResolverFactoryImpl factory) {
            super(referent, q);
            this.control = ctrl;
            this.factory = factory;
            this.openingException = factory.logUnclosedResolvers && LOG.isInfoEnabled() ? new Exception("Opening Stacktrace") : null;
        }

        public void close() {
            try {
                if (factory.unregisterControl(this.control) && factory.logUnclosedResolvers) {
                    if (factory.isLive()) {
                        LOG.warn("Closed unclosed ResourceResolver. The creation stacktrace is available on info log level.");
                    } else {
                        LOG.warn("Forced close of ResourceResolver because the ResourceResolverFactory is shutting down.");
                    }
                    LOG.info("Unclosed ResourceResolver was created here: ", openingException);
                }
            } catch (Throwable t) {
                LOG.warn("Exception while closing ResolverReference", t);
            }
        }
    }
}