/*
 * 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 javax.annotation.Nonnull;

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.
     */
    @Nonnull
    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)
     */
    @Nonnull
    @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)
     */
    @Nonnull
    @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());
        } 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();
    }

    @Nonnull
    @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);
            }
        }
    }
}