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

import org.apache.commons.collections4.map.LRUMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.QuerySyntaxException;
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.api.resource.ValueMap;
import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
import org.apache.sling.resourceresolver.impl.ResourceResolverMetrics;
import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
import org.jetbrains.annotations.NotNull;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;

public class MapEntries implements
    MapEntriesHandler,
    ResourceChangeListener,
    ExternalResourceChangeListener {

    private static final String JCR_CONTENT = "jcr:content";

    private static final String JCR_CONTENT_PREFIX = "jcr:content/";

    private static final String JCR_CONTENT_SUFFIX = "/jcr:content";

    private static final String PROP_REG_EXP = "sling:match";

    public static final String PROP_REDIRECT_EXTERNAL = "sling:redirect";

    public static final String PROP_REDIRECT_EXTERNAL_STATUS = "sling:status";

    public static final String PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS = "sling:redirectStatus";

    public static final String PROP_VANITY_PATH = "sling:vanityPath";

    public static final String PROP_VANITY_ORDER = "sling:vanityOrder";

    private static final int VANITY_BLOOM_FILTER_MAX_ENTRIES = 10000000;

    /** Key for the global list. */
    private static final String GLOBAL_LIST_KEY = "*";

    public static final String DEFAULT_MAP_ROOT = "/etc/map";

    public static final int DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS = HttpServletResponse.SC_FOUND;

    @SuppressWarnings("java:S1075") // Repository path
    private static final String JCR_SYSTEM_PATH = "/jcr:system";

    private static final String JCR_SYSTEM_PREFIX = JCR_SYSTEM_PATH + '/';

    static final String ANY_SCHEME_HOST = "[^/]+/[^/]+";

    /** default log */
    private final Logger log = LoggerFactory.getLogger(MapEntries.class);

    private volatile MapConfigurationProvider factory;

    private volatile ResourceResolver resolver;

    private volatile EventAdmin eventAdmin;

    private Optional<ResourceResolverMetrics> metrics;

    private volatile ServiceRegistration<ResourceChangeListener> registration;

    private Map<String, List<MapEntry>> resolveMapsMap;

    // Temporary cache for use while doing async vanity path query
    private Map<String, List<MapEntry>> temporaryResolveMapsMap;
    private List<Map.Entry<String, ResourceChange.ChangeType>> resourceChangeQueue;
    private AtomicLong temporaryResolveMapsMapHits = new AtomicLong();
    private AtomicLong temporaryResolveMapsMapMisses = new AtomicLong();

    private Collection<MapEntry> mapMaps;

    private Map <String,List <String>> vanityTargets;

    /**
     * The key of the map is the parent path, while the value is a map with the the resource name as key and the actual aliases as values)
     */
    private Map<String, Map<String, Collection<String>>> aliasMapsMap;

    private final AtomicLong aliasResourcesOnStartup;

    private final ReentrantLock initializing = new ReentrantLock();

    private final AtomicLong vanityCounter;
    private final AtomicLong vanityResourcesOnStartup;
    private final AtomicLong vanityPathLookups;
    private final AtomicLong vanityPathBloomNegative;
    private final AtomicLong vanityPathBloomFalsePositive;

    private byte[] vanityBloomFilter;

    private AtomicBoolean vanityPathsProcessed = new AtomicBoolean(false);

    private final StringInterpolationProvider stringInterpolationProvider;

    private final boolean useOptimizeAliasResolution;
    public MapEntries(final MapConfigurationProvider factory, 
            final BundleContext bundleContext, 
            final EventAdmin eventAdmin, 
            final StringInterpolationProvider stringInterpolationProvider, 
            final Optional<ResourceResolverMetrics> metrics) 
                    throws LoginException, IOException {

        this.resolver = factory.getServiceResourceResolver(factory.getServiceUserAuthenticationInfo("mapping"));
        this.factory = factory;
        this.eventAdmin = eventAdmin;

        this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, Collections.emptyList());
        this.mapMaps = Collections.<MapEntry> emptyList();
        this.vanityTargets = Collections.<String,List <String>>emptyMap();
        this.aliasMapsMap = new ConcurrentHashMap<>();
        this.stringInterpolationProvider = stringInterpolationProvider;

        this.aliasResourcesOnStartup = new AtomicLong(0);

        this.useOptimizeAliasResolution = doInit();

        this.registration = registerResourceChangeListener(bundleContext);

        this.vanityCounter = new AtomicLong(0);
        this.vanityResourcesOnStartup = new AtomicLong(0);
        this.vanityPathLookups = new AtomicLong(0);
        this.vanityPathBloomNegative = new AtomicLong(0);
        this.vanityPathBloomFalsePositive = new AtomicLong(0);
        initializeVanityPaths();

        this.metrics = metrics;
        if (metrics.isPresent()) {
            this.metrics.get().setNumberOfVanityPathsSupplier(vanityCounter::get);
            this.metrics.get().setNumberOfResourcesWithVanityPathsOnStartupSupplier(vanityResourcesOnStartup::get);
            this.metrics.get().setNumberOfVanityPathLookupsSupplier(vanityPathLookups::get);
            this.metrics.get().setNumberOfVanityPathBloomNegativeSupplier(vanityPathBloomNegative::get);
            this.metrics.get().setNumberOfVanityPathBloomFalsePositiveSupplier(vanityPathBloomFalsePositive::get);
            this.metrics.get().setNumberOfResourcesWithAliasedChildrenSupplier(() -> (long) aliasMapsMap.size());
            this.metrics.get().setNumberOfResourcesWithAliasesOnStartupSupplier(aliasResourcesOnStartup::get);
        }
    }

    private ServiceRegistration<ResourceChangeListener> registerResourceChangeListener(final BundleContext bundleContext) {
        final Dictionary<String, Object> props = new Hashtable<>(); // NOSONAR - required by OSGi APIs
        final String[] paths = new String[factory.getObservationPaths().length];
        for (int i = 0; i < paths.length; i++) {
            paths[i] = factory.getObservationPaths()[i].getPath();
        }
        props.put(ResourceChangeListener.PATHS, paths);
        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Map Entries Observation");
        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
        log.info("Registering for {}", Arrays.toString(factory.getObservationPaths()));

        this.resourceChangeQueue = Collections.synchronizedList(new LinkedList<>());
        return bundleContext.registerService(ResourceChangeListener.class, this, props);
    }

    /**
     * Actual initializer. Guards itself against concurrent use by using a
     * ReentrantLock. Does nothing if the resource resolver has already been
     * null-ed.
     */
    protected boolean doInit() {

        this.initializing.lock();
        try {
            final ResourceResolver resolver = this.resolver;
            final MapConfigurationProvider factory = this.factory;
            if (resolver == null || factory == null) {
                return this.factory.isOptimizeAliasResolutionEnabled();
            }

            boolean isOptimizeAliasResolutionEnabled = this.factory.isOptimizeAliasResolutionEnabled();

            //optimization made in SLING-2521
            if (isOptimizeAliasResolutionEnabled) {
                try {
                    final Map<String, Map<String, Collection<String>>> loadedMap = this.loadAliases(resolver);
                    this.aliasMapsMap = loadedMap;
    
                } catch (final Exception e) {

                    logDisableAliasOptimization(e);

                    // disable optimize alias resolution
                    isOptimizeAliasResolutionEnabled = false;
                }
            }

            this.resolveMapsMap = new ConcurrentHashMap<>();

            doUpdateConfiguration();

            sendChangeEvent();

            return isOptimizeAliasResolutionEnabled;

        } finally {

            this.initializing.unlock();

        }
    }

    /**
     * Actual vanity paths initializer. Guards itself against concurrent use by
     * using a ReentrantLock. Does nothing if the resource resolver has already
     * been null-ed.
     *
     * @throws IOException
     */
    protected void initializeVanityPaths() throws IOException {
        this.initializing.lock();
        try {
            if (this.factory.isVanityPathEnabled()) {
                this.vanityBloomFilter = createVanityBloomFilter();
                VanityPathInitializer vpi = new VanityPathInitializer(this.factory);
                if (this.factory.isVanityPathCacheInitInBackground()) {
                    this.log.debug("bg init starting");
                    Thread vpinit = new Thread(vpi, "VanityPathInitializer");
                    vpinit.start();
                } else {
                    vpi.run();
                }
            }
        } finally {
            this.initializing.unlock();
        }
    }

    private class VanityPathInitializer implements Runnable {

        private int SIZELIMIT = 10000;

        private MapConfigurationProvider factory;

        public VanityPathInitializer(MapConfigurationProvider factory) {
            this.factory = factory;
        }

        @Override
        public void run() {
            temporaryResolveMapsMap = Collections.synchronizedMap(new LRUMap<>(SIZELIMIT));
            execute();
        }

        private void drainQueue(List<Map.Entry<String, ResourceChange.ChangeType>> queue) {
            final AtomicBoolean resolverRefreshed = new AtomicBoolean(false);

            // send the change event only once
            boolean sendEvent = false;

            // the config needs to be reloaded only once
            final AtomicBoolean hasReloadedConfig = new AtomicBoolean(false);

            while (!queue.isEmpty()) {
                Map.Entry<String, ResourceChange.ChangeType> entry = queue.remove(0);
                final ResourceChange.ChangeType type = entry.getValue();
                final String path = entry.getKey();

                log.trace("drain type={}, path={}", type, path);
                boolean changed = handleResourceChange(type, path, resolverRefreshed, hasReloadedConfig);

                if (changed) {
                    sendEvent = true;
                }
            }

            if (sendEvent) {
                sendChangeEvent();
            }
        }

        private void execute() {
            try (ResourceResolver resolver = factory
                    .getServiceResourceResolver(factory.getServiceUserAuthenticationInfo("mapping"))) {

                long initStart = System.nanoTime();
                log.debug("vanity path initialization - start");

                vanityTargets = loadVanityPaths(resolver);

                // process pending event
                drainQueue(resourceChangeQueue);

                vanityPathsProcessed.set(true);

                // drain once more in case more events have arrived
                drainQueue(resourceChangeQueue);

                long initElapsed = System.nanoTime() - initStart;
                long resourcesPerSecond = (vanityResourcesOnStartup.get() * TimeUnit.SECONDS.toNanos(1) / (initElapsed == 0 ? 1 : initElapsed));
                log.info(
                        "vanity path initialization - completed, processed {} resources with sling:vanityPath properties in {}ms (~{} resource/s)",
                        vanityResourcesOnStartup.get(), TimeUnit.NANOSECONDS.toMillis(initElapsed), resourcesPerSecond);
            } catch (LoginException ex) {
                log.error("Vanity path init failed", ex);
            } finally {
                log.debug("dropping temporary resolver map - {}/{} entries, {} hits, {} misses", temporaryResolveMapsMap.size(),
                        SIZELIMIT, temporaryResolveMapsMapHits.get(), temporaryResolveMapsMapMisses.get());
                temporaryResolveMapsMap = null;
            }
        }
    }

    private boolean addResource(final String path, final AtomicBoolean resolverRefreshed) {
        this.initializing.lock();

        try {
            this.refreshResolverIfNecessary(resolverRefreshed);
            final Resource resource = this.resolver != null ? resolver.getResource(path) : null;
            if (resource != null) {
                boolean changed = doAddVanity(resource);
                if (this.useOptimizeAliasResolution && resource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
                    changed |= doAddAlias(resource);
                }
                return changed;
            }

            return false;
        } finally {
            this.initializing.unlock();
        }
    }

    private boolean updateResource(final String path, final AtomicBoolean resolverRefreshed) {
        final boolean isValidVanityPath =  this.isValidVanityPath(path);
        if ( this.useOptimizeAliasResolution || isValidVanityPath) {
            this.initializing.lock();

            try {
                this.refreshResolverIfNecessary(resolverRefreshed);
                final Resource resource = this.resolver != null ? resolver.getResource(path) : null;
                if (resource != null) {
                    boolean changed = false;
                    if ( isValidVanityPath ) {
                        // we remove the old vanity path first
                        changed |= doRemoveVanity(path);

                        // add back vanity path
                        Resource contentRsrc = null;
                        if ( !resource.getName().equals(JCR_CONTENT)) {
                            // there might be a JCR_CONTENT child resource
                            contentRsrc = resource.getChild(JCR_CONTENT);
                        }
                        changed |= doAddVanity(contentRsrc != null ? contentRsrc : resource);
                    }
                    if (this.useOptimizeAliasResolution) {
                        changed |= doUpdateAlias(resource);
                    }

                    return changed;
                }
            } finally {
                this.initializing.unlock();
            }
        }

        return false;
    }

    private boolean removeResource(final String path, final AtomicBoolean resolverRefreshed) {
        boolean changed = false;
        final String actualContentPath = getActualContentPath(path);
        final String actualContentPathPrefix = actualContentPath + "/";

        for (final String target : this.vanityTargets.keySet()) {
            if (target.startsWith(actualContentPathPrefix) || target.equals(actualContentPath)) {
                changed |= removeVanityPath(target);
            }
        }
        if (this.useOptimizeAliasResolution) {
            final String pathPrefix = path + "/";
            for (final String contentPath : this.aliasMapsMap.keySet()) {
                if (path.startsWith(contentPath + "/") || path.equals(contentPath)
                        || contentPath.startsWith(pathPrefix)) {
                    changed |= removeAlias(contentPath, path, resolverRefreshed);
                }
            }
        }
        return changed;
    }

    /**
     * Remove all aliases for the content path
     * @param contentPath The content path
     * @param path Optional sub path of the vanity path
     * @return {@code true} if a change happened
     */
    private boolean removeAlias(final String contentPath, final String path, final AtomicBoolean resolverRefreshed) {
        // if path is specified we first need to find out if it is
        // a direct child of vanity path but not jcr:content, or a jcr:content child of a direct child
        // otherwise we can discard the event
        boolean handle = true;
        final String resourcePath;
        if ( path != null  && path.length() > contentPath.length()) {
            final String subPath = path.substring(contentPath.length() + 1);
            final int firstSlash = subPath.indexOf('/');
            if ( firstSlash == -1 ) {
                if ( subPath.equals(JCR_CONTENT) ) {
                    handle = false;
                }
                resourcePath = path;
            } else if ( subPath.lastIndexOf('/') == firstSlash) {
                if ( subPath.startsWith(JCR_CONTENT_PREFIX) || !subPath.endsWith(JCR_CONTENT_SUFFIX) ) {
                    handle = false;
                }
                resourcePath = ResourceUtil.getParent(path);
            } else {
                handle = false;
                resourcePath = null;
            }
        }
        else {
            resourcePath = contentPath;
        }
        if ( !handle ) {
            return false;
        }

        this.initializing.lock();
        try {
            final Map<String, Collection<String>> aliasMapEntry = aliasMapsMap.get(contentPath);
            if (aliasMapEntry != null) {
                this.refreshResolverIfNecessary(resolverRefreshed);

                String prefix = contentPath.endsWith("/") ? contentPath : contentPath + "/";
                if (aliasMapEntry.entrySet().removeIf(e -> (prefix + e.getKey()).startsWith(resourcePath)) &&  (aliasMapEntry.isEmpty())) {
                    this.aliasMapsMap.remove(contentPath);
                }

                Resource containingResource = this.resolver != null ? this.resolver.getResource(resourcePath) : null;

                if (containingResource != null) {
                    if (containingResource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
                        doAddAlias(containingResource);
                    }
                    final Resource child = containingResource.getChild(JCR_CONTENT);
                    if (child != null && child.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
                        doAddAlias(child);
                    }
                }
            }
            return aliasMapEntry != null;
        } finally {
            this.initializing.unlock();
        }
    }

    private boolean removeVanityPath(final String path) {
        this.initializing.lock();
        try {
            return doRemoveVanity(path);
        } finally {
            this.initializing.unlock();
        }
    }

    /**
     * Update the configuration.
     * Does no locking and does not send an event at the end
     */
    private void doUpdateConfiguration() {
        final List<MapEntry> globalResolveMap = new ArrayList<>();
        final SortedMap<String, MapEntry> newMapMaps = new TreeMap<>();
        // load the /etc/map entries into the maps
        loadResolverMap(resolver, globalResolveMap, newMapMaps);
        // load the configuration into the resolver map
        loadConfiguration(factory, globalResolveMap);
        // load the configuration into the mapper map
        loadMapConfiguration(factory, newMapMaps);
        // sort global list and add to map
        Collections.sort(globalResolveMap);
        resolveMapsMap.put(GLOBAL_LIST_KEY, globalResolveMap);
        this.mapMaps = Collections.unmodifiableSet(new TreeSet<>(newMapMaps.values()));
    }

    private boolean doAddVanity(final Resource resource) {
        log.debug("doAddVanity getting {}", resource.getPath());

        boolean updateTheCache = isAllVanityPathEntriesCached() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries();
        return null != loadVanityPath(resource, resolveMapsMap, vanityTargets, updateTheCache);
    }

    private boolean doRemoveVanity(final String path) {
        final String actualContentPath = getActualContentPath(path);
        final List <String> l = vanityTargets.remove(actualContentPath);
        if (l != null){
            for (final String s : l){
                final List<MapEntry> entries = this.resolveMapsMap.get(s);
                if (entries!= null) {
                    for (final Iterator<MapEntry> iterator =entries.iterator(); iterator.hasNext(); ) {
                        final MapEntry entry = iterator.next();
                        final String redirect = getMapEntryRedirect(entry);
                        if (redirect != null && redirect.equals(actualContentPath)) {
                            iterator.remove();
                        }
                    }
                }
                if (entries!= null && entries.isEmpty()) {
                    this.resolveMapsMap.remove(s);
                }
            }
            if (vanityCounter.longValue() > 0) {
                vanityCounter.addAndGet(-2);
            }
            return true;
        }
        return false;
    }

    private boolean doAddAlias(final Resource resource) {
        return loadAlias(resource, this.aliasMapsMap);
    }

    /**
     * Update alias from a resource
     * @param resource The resource
     * @return {@code true} if any change
     */
    private boolean doUpdateAlias(final Resource resource) {
        final Resource containingResource;
        if (JCR_CONTENT.equals(resource.getName())) {
            containingResource = resource.getParent();
        } else {
            containingResource = resource;
        }

        if ( containingResource != null ) {
            final String containingResourceName = containingResource.getName();
            final String parentPath = ResourceUtil.getParent(containingResource.getPath());

            final Map<String, Collection<String>> aliasMapEntry = parentPath == null ? null : aliasMapsMap.get(parentPath);
            if (aliasMapEntry != null) {
                aliasMapEntry.remove(containingResourceName);
                if (aliasMapEntry.isEmpty()) {
                    this.aliasMapsMap.remove(parentPath);
                }
            }

            boolean changed = aliasMapEntry != null;

            if ( containingResource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS) ) {
                changed |= doAddAlias(containingResource);
            }
            final Resource child = containingResource.getChild(JCR_CONTENT);
            if ( child != null && child.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS) ) {
                changed |= doAddAlias(child);
            }

            return changed;
        }
        return false;
    }

    /**
     * Cleans up this class.
     */
    public void dispose() {

        if (this.registration != null) {
            this.registration.unregister();
            this.registration = null;
        }

        /*
         * Cooperation with doInit: The same lock as used by doInit is acquired
         * thus preventing doInit from running and waiting for a concurrent
         * doInit to terminate. Once the lock has been acquired, the resource
         * resolver is null-ed (thus causing the init to terminate when
         * triggered the right after and prevent the doInit method from doing
         * any thing).
         */

        // wait at most 10 seconds for a notifcation during initialization
        boolean initLocked;
        try {
            initLocked = this.initializing.tryLock(10, TimeUnit.SECONDS);
        } catch (final InterruptedException ie) {
            initLocked = false;
        }

        try {
            if (!initLocked) {
                log.warn("dispose: Could not acquire initialization lock within 10 seconds; ongoing intialization may fail");
            }

            // immediately set the resolver field to null to indicate
            // that we have been disposed (this also signals to the
            // event handler to stop working
            final ResourceResolver oldResolver = this.resolver;
            this.resolver = null;

            if (oldResolver != null) {
                oldResolver.close();
            } else {
                log.warn("dispose: ResourceResolver has already been cleared before; duplicate call to dispose ?");
            }
        } finally {
            if (initLocked) {
                this.initializing.unlock();
            }
        }

        // clear the rest of the fields
        this.factory = null;
        this.eventAdmin = null;
    }

    @Override
    public List<MapEntry> getResolveMaps() {
        final List<MapEntry> entries = new ArrayList<>();
        for (final List<MapEntry> list : this.resolveMapsMap.values()) {
            entries.addAll(list);
        }
        Collections.sort(entries);
        return Collections.unmodifiableList(entries);
    }

    @Override
    public Iterator<MapEntry> getResolveMapsIterator(final String requestPath) {
        String key = null;
        final int firstIndex = requestPath.indexOf('/');
        final int secondIndex = requestPath.indexOf('/', firstIndex + 1);
        if (secondIndex != -1) {
            key = requestPath.substring(secondIndex);
        }

        return new MapEntryIterator(key, resolveMapsMap, this.factory.hasVanityPathPrecedence());
    }

    @Override
    public Collection<MapEntry> getMapMaps() {
        return mapMaps;
    }

    public boolean isOptimizeAliasResolutionEnabled() {
        return this.useOptimizeAliasResolution;
    }
    
    @Override
    public @NotNull Map<String, Collection<String>> getAliasMap(final String parentPath) {
        Map<String, Collection<String>> aliasMapForParent = aliasMapsMap.get(parentPath);
        return aliasMapForParent != null ? aliasMapForParent : Collections.emptyMap();
    }

    @Override
    public Map<String, List<String>> getVanityPathMappings() {
        return Collections.unmodifiableMap(vanityTargets);
    }

    // special singleton entry for negative cache entries
    private static final List<MapEntry> NO_MAP_ENTRIES = Collections.emptyList();

    /**
     * get the MapEntry list containing all the nodes having a specific vanityPath
     */
    private List<MapEntry> getMapEntryList(String vanityPath) {
        List<MapEntry> mapEntries = null;

        boolean initFinished = vanityPathsProcessed.get();
        boolean probablyPresent = false;

        if (initFinished) {
            // total number of lookups after init (and when cache not complete)
            long current = this.vanityPathLookups.incrementAndGet();
            if (current >= Long.MAX_VALUE - 100000) {
                // reset counters when we get close the limit
                this.vanityPathLookups.set(1);
                this.vanityPathBloomNegative.set(0);
                this.vanityPathBloomFalsePositive.set(0);
                log.info("Vanity Path metrics reset to 0");
            }

            // init is done - check the bloom filter
            probablyPresent = BloomFilterUtils.probablyContains(vanityBloomFilter, vanityPath);
            log.trace("bloom filter lookup for {} -> {}", vanityPath, probablyPresent);

            if (!probablyPresent) {
                // filtered by Bloom filter
                this.vanityPathBloomNegative.incrementAndGet();
            }
        }

        if (!initFinished || probablyPresent) {

            mapEntries = this.resolveMapsMap.get(vanityPath);

            if (mapEntries == null) {
                if (!initFinished && temporaryResolveMapsMap != null) {
                    mapEntries = temporaryResolveMapsMap.get(vanityPath);
                    if (mapEntries != null) {
                        temporaryResolveMapsMapHits.incrementAndGet();
                        log.trace("getMapEntryList: using temp map entries for {} -> {}", vanityPath, mapEntries);
                    } else {
                        temporaryResolveMapsMapMisses.incrementAndGet();
                    }
                }
                if (mapEntries == null) {
                    Map<String, List<MapEntry>> mapEntry = getVanityPaths(vanityPath);
                    mapEntries = mapEntry.get(vanityPath);
                    if (!initFinished && temporaryResolveMapsMap != null) {
                        log.trace("getMapEntryList: caching map entries for {} -> {}", vanityPath, mapEntries);
                        temporaryResolveMapsMap.put(vanityPath, mapEntries == null ? NO_MAP_ENTRIES : mapEntries);
                    }
                }
            }
            if (mapEntries == null && probablyPresent) {
                // Bloom filter had a false positive
                this.vanityPathBloomFalsePositive.incrementAndGet();
            }
        }

        return mapEntries == NO_MAP_ENTRIES ? null : mapEntries;
    }

    /**
     * Refresh the resource resolver if not already done
     * @param resolverRefreshed Boolean flag containing the state if the resolver
     *                          has been refreshed. True in any case when this
     *                          method returns
     */
    private void refreshResolverIfNecessary(final AtomicBoolean resolverRefreshed) {
        if ( resolverRefreshed.compareAndSet(false, true) ) {
            this.resolver.refresh();
        }
    }

    /**
     * Checks if the path affects the map configuration. If it does
     * the configuration is updated.
     * @param path The changed path (could be add/remove/update)
     * @param hasReloadedConfig If this is already true, the config will not be reloaded
     * @param resolverRefreshed Boolean flag handling resolver refresh
     * @param isDelete If this is a delete event
     * @return {@code true} if the configuration has been updated, {@code false} if
     *         the path does not affect a config change, {@code null} if the config has already
     *         been reloaded.
     */
    private Boolean handleConfigurationUpdate(final String path,
            final AtomicBoolean hasReloadedConfig,
            final AtomicBoolean resolverRefreshed,
            final boolean isDelete) {
        if ( this.factory.isMapConfiguration(path)
             || (isDelete && this.factory.getMapRoot().startsWith(path + "/")) ) {
            if ( hasReloadedConfig.compareAndSet(false, true) ) {
                this.initializing.lock();

                try {
                    if (this.resolver != null) {
                        refreshResolverIfNecessary(resolverRefreshed);
                        doUpdateConfiguration();
                    }
                } finally {
                    this.initializing.unlock();
                }
                return true;
            }
            return null;
        }
        return false;
    }

    // ---------- ResourceChangeListener interface

    /**
     * Handles the change to any of the node properties relevant for vanity URL
     * mappings. The {@link #MapEntries(MapConfigurationProvider, BundleContext, EventAdmin, StringInterpolationProvider, Optional)}
     * constructor makes sure the event listener is registered to only get
     * appropriate events.
     */
    @Override
    public void onChange(final List<ResourceChange> changes) {

        final boolean inStartup = !vanityPathsProcessed.get();

        final AtomicBoolean resolverRefreshed = new AtomicBoolean(false);

        // send the change event only once
        boolean sendEvent = false;

        // the config needs to be reloaded only once
        final AtomicBoolean hasReloadedConfig = new AtomicBoolean(false);

        for (final ResourceChange rc : changes) {

            final ResourceChange.ChangeType type = rc.getType();
            final String path = rc.getPath();

            log.debug("onChange, type={}, path={}", rc.getType(), path);

            // don't care for system area
            if (path.startsWith(JCR_SYSTEM_PREFIX)) {
                continue;
            }

            // during startup: just enqueue the events
            if (inStartup) {
                if (type == ResourceChange.ChangeType.REMOVED || type == ResourceChange.ChangeType.ADDED
                        || type == ResourceChange.ChangeType.CHANGED) {
                    Map.Entry<String, ResourceChange.ChangeType> entry = new SimpleEntry<>(path, type);
                    log.trace("enqueue: {}", entry);
                    resourceChangeQueue.add(entry);
                }
            } else {
                boolean changed = handleResourceChange(type, path, resolverRefreshed, hasReloadedConfig);

                if (changed) {
                    sendEvent = true;
                }
            }
        }

        if (sendEvent) {
            this.sendChangeEvent();
        }
    }

    private boolean handleResourceChange(ResourceChange.ChangeType type, String path, AtomicBoolean resolverRefreshed,
            AtomicBoolean hasReloadedConfig) {
        boolean changed = false;

        // removal of a resource is handled differently
        if (type == ResourceChange.ChangeType.REMOVED) {
            final Boolean result = handleConfigurationUpdate(path, hasReloadedConfig, resolverRefreshed, true);
            if (result != null) {
                if (result) {
                    changed = true;
                } else {
                    changed |= removeResource(path, resolverRefreshed);
                }
            }
            // session.move() is handled differently see also SLING-3713 and
        } else if (type == ResourceChange.ChangeType.ADDED) {
            final Boolean result = handleConfigurationUpdate(path, hasReloadedConfig, resolverRefreshed, false);
            if (result != null) {
                if (result) {
                    changed = true;
                } else {
                    changed |= addResource(path, resolverRefreshed);
                }
            }
        } else if (type == ResourceChange.ChangeType.CHANGED) {
            final Boolean result = handleConfigurationUpdate(path, hasReloadedConfig, resolverRefreshed, false);
            if (result != null) {
                if (result) {
                    changed = true;
                } else {
                    changed |= updateResource(path, resolverRefreshed);
                }
            }
        }

        return changed;
    }

    // ---------- internal

    private byte[] createVanityBloomFilter() throws IOException {
        return BloomFilterUtils.createFilter(VANITY_BLOOM_FILTER_MAX_ENTRIES, this.factory.getVanityBloomFilterMaxBytes());
    }

    private boolean isAllVanityPathEntriesCached() {
        return this.factory.getMaxCachedVanityPathEntries() == -1;
    }

    // escapes string for use as literal in JCR SQL within single quotes
    private static String queryLiteral(String input) {
        return input.replace("'", "''");
    }

    /**
     * get the vanity paths  Search for all nodes having a specific vanityPath
     */
    private Map<String, List<MapEntry>> getVanityPaths(String vanityPath) {

        Map<String, List<MapEntry>> entryMap = new HashMap<>();

        final String queryString = String.format(
                "SELECT [sling:vanityPath], [sling:redirect], [sling:redirectStatus] FROM [nt:base] "
                        + "WHERE NOT isdescendantnode('%s') AND ([sling:vanityPath]='%s' OR [sling:vanityPath]='%s') "
                        + "ORDER BY [sling:vanityOrder] DESC",
                JCR_SYSTEM_PATH, queryLiteral(vanityPath), queryLiteral(vanityPath.substring(1)));

        try (ResourceResolver queryResolver = factory.getServiceResourceResolver(factory.getServiceUserAuthenticationInfo("mapping"));) {
            long totalCount = 0;
            long totalValid = 0;
            log.debug("start vanityPath query: {}", queryString);
            final Iterator<Resource> i = queryResolver.findResources(queryString, "JCR-SQL2");
            log.debug("end vanityPath query");
            while (i.hasNext()) {
                totalCount += 1;
                final Resource resource = i.next();
                boolean isValid = false;
                for(final Path sPath : this.factory.getObservationPaths()) {
                    if ( sPath.matches(resource.getPath())) {
                        isValid = true;
                        break;
                    }
                }
                if ( isValid ) {
                    totalValid += 1;
                    if (this.vanityPathsProcessed.get() && (this.factory.isMaxCachedVanityPathEntriesStartup() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries())) {
                        loadVanityPath(resource, resolveMapsMap, vanityTargets, true);
                        entryMap = resolveMapsMap;
                    } else {
                        final Map <String, List<String>> targetPaths = new HashMap<>();
                        loadVanityPath(resource, entryMap, targetPaths, true);
                    }
                }
            }
            log.debug("read {} ({} valid) vanityPaths", totalCount, totalValid);
        } catch (LoginException e) {
            log.error("Exception while obtaining queryResolver", e);
        }
        return entryMap;
    }

    /**
     * Check if the path is a valid vanity path
     * @param path The resource path to check
     * @return {@code true} if this is valid, {@code false} otherwise
     */
    private boolean isValidVanityPath(final String path){
        if (path == null) {
            throw new IllegalArgumentException("Unexpected null path");
        }

        // ignore system tree
        if (path.startsWith(JCR_SYSTEM_PREFIX)) {
            log.debug("isValidVanityPath: not valid {}", path);
            return false;
        }

        // check allow/deny list
        if ( this.factory.getVanityPathConfig() != null ) {
            boolean allowed = false;
            for(final VanityPathConfig config : this.factory.getVanityPathConfig()) {
                if ( path.startsWith(config.prefix) ) {
                    allowed = !config.isExclude;
                    break;
                }
            }
            if ( !allowed ) {
                log.debug("isValidVanityPath: not valid as not in allow list {}", path);
                return false;
            }
        }
        return true;
    }

    private String getActualContentPath(final String path){
        final String checkPath;
        if ( path.endsWith(JCR_CONTENT_SUFFIX) ) {
            checkPath = ResourceUtil.getParent(path);
        } else {
            checkPath = path;
        }
        return checkPath;
    }

    private String getMapEntryRedirect(final  MapEntry mapEntry) {
        String[] redirect = mapEntry.getRedirect();
        if (redirect.length > 1) {
            log.warn("something went wrong, please restart the bundle");
            return null;
        }

        String path = redirect[0];
        if (path.endsWith("$1")) {
            path = path.substring(0, path.length() - "$1".length());
        } else if (path.endsWith(".html")) {
            path = path.substring(0, path.length() - ".html".length());
        }

        return path;
    }

    /**
     * Send an OSGi event
     */
    private void sendChangeEvent() {
        final EventAdmin local = this.eventAdmin;
        if (local != null) {
            final Event event = new Event(SlingConstants.TOPIC_RESOURCE_RESOLVER_MAPPING_CHANGED,
                            (Dictionary<String, ?>) null);
            local.postEvent(event);
        }
    }

    private void loadResolverMap(final ResourceResolver resolver, final List<MapEntry> entries, final Map<String, MapEntry> mapEntries) {
        // the standard map configuration
        final Resource res = resolver.getResource(this.factory.getMapRoot());
        if (res != null) {
            gather(resolver, entries, mapEntries, res, "");
        }
    }

    private void gather(final ResourceResolver resolver, final List<MapEntry> entries, final Map<String, MapEntry> mapEntries,
                    final Resource parent, final String parentPath) {
        // scheme list
        final Iterator<Resource> children = parent.listChildren();
        while (children.hasNext()) {
            final Resource child = children.next();
            final ValueMap vm = ResourceUtil.getValueMap(child);

            String name = vm.get(PROP_REG_EXP, String.class);
            boolean trailingSlash = false;
            if (name == null) {
                name = child.getName().concat("/");
                trailingSlash = true;
            }
            // Check for placeholders and replace if needed
            name = stringInterpolationProvider.substitute(name);

            final String childPath = parentPath.concat(name);

            // gather the children of this entry (only if child is not end
            // hooked)
            if (!childPath.endsWith("$")) {

                // add trailing slash to child path to append the child
                String childParent = childPath;
                if (!trailingSlash) {
                    childParent = childParent.concat("/");
                }

                gather(resolver, entries, mapEntries, child, childParent);
            }

            // add resolution entries for this node
            MapEntry childResolveEntry = null;
            try{
                childResolveEntry=MapEntry.createResolveEntry(childPath, child, trailingSlash);
            }catch (IllegalArgumentException iae){
                //ignore this entry
                log.debug("ignored entry due exception ",iae);
            }
            if (childResolveEntry != null) {
                entries.add(childResolveEntry);
            }

            // add map entries for this node
            final List<MapEntry> childMapEntries = MapEntry.createMapEntry(childPath, child, trailingSlash);
            if (childMapEntries != null) {
                for (final MapEntry mapEntry : childMapEntries) {
                    addMapEntry(mapEntries, mapEntry.getPattern(), mapEntry.getRedirect()[0], mapEntry.getStatus());
                }
            }

        }
    }

    /**
     * Add an entry to the resolve map.
     */
    private boolean addEntry(final Map<String, List<MapEntry>> entryMap, final String key, final MapEntry entry) {

        if (entry == null) {
            log.trace("trying to add null entry for {}", key);
            return false;
        } else {
            List<MapEntry> entries = entryMap.get(key);
            if (entries == null) {
                entries = new ArrayList<>();
                entries.add(entry);
                entryMap.put(key, entries);
            } else {
                List<MapEntry> entriesCopy = new ArrayList<>(entries);
                entriesCopy.add(entry);
                // and finally sort list
                Collections.sort(entriesCopy);
                entryMap.put(key, entriesCopy);
                int size = entriesCopy.size();
                if (size == 10) {
                    log.debug(">= 10 MapEntries for {} - check your configuration", key);
                } else if (size == 100) {
                    log.info(">= 100 MapEntries for {} - check your configuration", key);
                }
            }
            return true;
        }
    }

    /**
     * Load aliases - Search for all nodes (except under /jcr:system) below
     * configured alias locations having the sling:alias property
     */
    private Map<String, Map<String, Collection<String>>> loadAliases(final ResourceResolver resolver) {
        final Map<String, Map<String, Collection<String>>> map = new ConcurrentHashMap<>();
        final String baseQueryString = generateAliasQuery();

        Iterator<Resource> it;
        try {
            final String queryStringWithSort = baseQueryString + " AND FIRST([sling:alias]) > '%s' ORDER BY FIRST([sling:alias])";
            it = new PagedQueryIterator("alias", "sling:alias", resolver, queryStringWithSort, 2000);
        } catch (QuerySyntaxException ex) {
            log.debug("sort with first() not supported, falling back to base query", ex);
            it = queryUnpaged("alias", baseQueryString);
        } catch (UnsupportedOperationException ex) {
            log.debug("query failed as unsupported, retrying without paging/sorting", ex);
            it = queryUnpaged("alias", baseQueryString);
        }

        log.debug("alias initialization - start");
        long count = 0;
        long processStart = System.nanoTime();
        while (it.hasNext()) {
            count += 1;
            loadAlias(it.next(), map);
        }
        long processElapsed = System.nanoTime() - processStart;
        long resourcePerSecond = (count * TimeUnit.SECONDS.toNanos(1) / (processElapsed == 0 ? 1 : processElapsed));
        log.info("alias initialization - completed, processed {} resources with sling:alias properties in {}ms (~{} resource/s)",
                count, TimeUnit.NANOSECONDS.toMillis(processElapsed), resourcePerSecond);

        this.aliasResourcesOnStartup.set(count);

        return map;
    }

    /*
     * generate alias query based on configured alias locations
     */
    private String generateAliasQuery() {
        final Set<String> allowedLocations = this.factory.getAllowedAliasLocations();

        StringBuilder baseQuery = new StringBuilder("SELECT [sling:alias] FROM [nt:base] WHERE");

        if (allowedLocations.isEmpty()) {
            String jcrSystemPath = StringUtils.removeEnd(JCR_SYSTEM_PREFIX, "/");
            baseQuery.append(" NOT isdescendantnode('").append(queryLiteral(jcrSystemPath)).append("')");
        } else {
            Iterator<String> pathIterator = allowedLocations.iterator();
            baseQuery.append(" (");
            String sep = "";
            while (pathIterator.hasNext()) {
                String prefix = pathIterator.next();
                baseQuery.append(sep).append("isdescendantnode('").append(queryLiteral(prefix)).append("')");
                sep = " OR ";
            }
            baseQuery.append(")");
        }

        baseQuery.append(" AND [sling:alias] IS NOT NULL");
        return baseQuery.toString();
    }

    /**
     * Load alias given a resource
     */
    private boolean loadAlias(final Resource resource, Map<String, Map<String, Collection<String>>> map) {

        // resource containing the alias
        final Resource containingResource;

        if (JCR_CONTENT.equals(resource.getName())) {
            containingResource = resource.getParent();
        } else {
            containingResource = resource;
        }

        final Resource parent = containingResource.getParent();

        if (parent == null) {
            log.debug("parent is null for alias on {}.", resource.getName());
            return false;
        }
        else {
            // resource the alias is for
            String resourceName = containingResource.getName();

            // parent path of that resource
            String parentPath = parent.getPath();

            boolean hasAlias = false;

            // require properties
            final ValueMap props = resource.getValueMap();
            final String[] aliasArray = props.get(ResourceResolverImpl.PROP_ALIAS, String[].class);

            if (aliasArray != null) {
                log.debug("Found alias, total size {}", aliasArray.length);
                // the order matters here, the first alias in the array must come first
                for (final String alias : aliasArray) {
                    if (isAliasValid(alias)) {
                        log.warn("Encountered invalid alias {} under parent path {}. Refusing to use it.", alias, parentPath);
                    } else {
                        Map<String, Collection<String>> parentMap = map.computeIfAbsent(parentPath, key -> new ConcurrentHashMap<>());
                        Optional<String> siblingResourceNameWithDuplicateAlias = parentMap.entrySet().stream()
                                .filter(entry -> !entry.getKey().equals(resourceName)) // ignore entry for the current resource
                                .filter(entry -> entry.getValue().contains(alias))
                                .findFirst().map(Map.Entry::getKey);
                        if (siblingResourceNameWithDuplicateAlias.isPresent()) {
                            log.warn(
                                    "Encountered duplicate alias {} under parent path {}. Refusing to replace current target {} with {}.",
                                    alias, parentPath, siblingResourceNameWithDuplicateAlias.get(), resourceName);
                        } else {
                            Collection<String> existingAliases = parentMap.computeIfAbsent(resourceName, name -> new CopyOnWriteArrayList<>());
                            existingAliases.add(alias);
                            hasAlias = true;
                        }
                    }
                }
            }

            return hasAlias;
        }
    }

    /**
     * Check alias syntax
     */
    private static boolean isAliasValid(String alias) {
        boolean invalid = alias.equals("..") || alias.equals(".");
        if (!invalid) {
            for (final char c : alias.toCharArray()) {
                // invalid if / or # or a ?
                if (c == '/' || c == '#' || c == '?') {
                    invalid = true;
                    break;
                }
            }
        }
        return invalid;
    }

    private Iterator<Resource> queryUnpaged(String subject, String query) {
        log.debug("start {} query: {}", subject, query);
        long queryStart = System.nanoTime();
        final Iterator<Resource> it = resolver.findResources(query, "JCR-SQL2");
        long queryElapsed = System.nanoTime() - queryStart;
        log.debug("end {} query; elapsed {}ms", subject, TimeUnit.NANOSECONDS.toMillis(queryElapsed));
        return it;
    }

    /**
     * Utility class for running paged queries.
     */
    private class PagedQueryIterator implements Iterator<Resource> {

        private ResourceResolver resolver;
        private String subject;
        private String propertyName;
        private String query;
        private String lastValue = "";
        private Iterator<Resource> it;
        private int count = 0;
        private int page = 0;
        private int pageSize;
        private Resource next = null;
        private String[] defaultValue = new String[0];

        /**
         * @param subject name of the query, will be used only for logging
         * @param propertyName name of multivalued string property to query on
         * @param resolver resource resolver
         * @param query query string in SQL2 syntax
         * @param pageSize page size (start a new query after page size is exceeded)
         */
        public PagedQueryIterator(String subject, String propertyName, ResourceResolver resolver, String query, int pageSize) {
            this.subject = subject;
            this.propertyName = propertyName;
            this.resolver = resolver;
            this.query = query;
            this.pageSize = pageSize;
            nextPage();
        }

        private void nextPage() {
            count = 0;
            String tquery = String.format(query, queryLiteral(lastValue));
            log.debug("start {} query (page {}): {}", subject, page, tquery);
            long queryStart = System.nanoTime();
            this.it = resolver.findResources(tquery, "JCR-SQL2");
            long queryElapsed = System.nanoTime() - queryStart;
            log.debug("end {} query (page {}); elapsed {}ms", subject, page, TimeUnit.NANOSECONDS.toMillis(queryElapsed));
            page += 1;
        }

        private Resource getNext() throws NoSuchElementException {
            Resource resource = it.next();
            count += 1;
            final String[] values = resource.getValueMap().get(propertyName, defaultValue);
            if (values.length > 0) {
                String value = values[0];
                if (value.compareTo(lastValue) < 0) {
                    String message = String.format("unexpected query result in page %d, %s of '%s' despite querying for > '%s'",
                            (page - 1), propertyName, value, lastValue);
                    log.error(message);
                    throw new RuntimeException(message);
                }
                // start next page?
                if (count > pageSize && !value.equals(lastValue)) {
                    log.debug("read {} query (page {}); {} entries", subject, page, count);
                    lastValue = value;
                    nextPage();
                }
            }

            return resource;
        }

        @Override
        public boolean hasNext() {
            if (next == null) {
                try {
                    next = getNext();
                } catch (NoSuchElementException ex) {
                    // there are no more
                    next = null;
                }
            }
            return next != null;
        }

        @Override
        public Resource next() throws NoSuchElementException {
            Resource result = next != null ? next : getNext();
            next = null;
            return result;
        }
    }

    /**
     * Load vanity paths - search for all nodes (except under /jcr:system)
     * having a sling:vanityPath property
     */
    private Map<String, List<String>> loadVanityPaths(ResourceResolver resolver) {
        final Map<String, List<String>> targetPaths = new ConcurrentHashMap<>();
        final String baseQueryString = "SELECT [sling:vanityPath], [sling:redirect], [sling:redirectStatus]" + " FROM [nt:base]"
                + " WHERE NOT isdescendantnode('" + queryLiteral(JCR_SYSTEM_PATH) + "')"
                + " AND [sling:vanityPath] IS NOT NULL";

        boolean supportsSort = true;
        Iterator<Resource> it;
        try {
            final String queryStringWithSort = baseQueryString + " AND FIRST([sling:vanityPath]) > '%s' ORDER BY FIRST([sling:vanityPath])";
            it = new PagedQueryIterator("vanity path", PROP_VANITY_PATH, resolver, queryStringWithSort, 2000);
        } catch (QuerySyntaxException ex) {
            log.debug("sort with first() not supported, falling back to base query", ex);
            supportsSort = false;
            it = queryUnpaged("vanity path", baseQueryString);
        } catch (UnsupportedOperationException ex) {
            log.debug("query failed as unsupported, retrying without paging/sorting", ex);
            supportsSort = false;
            it = queryUnpaged("vanity path", baseQueryString);
        }

        long count = 0;
        long countInScope = 0;
        long processStart = System.nanoTime();
        String previousVanityPath = null;

        while (it.hasNext()) {
            count += 1;
            final Resource resource = it.next();
            final String resourcePath = resource.getPath();
            if (Stream.of(this.factory.getObservationPaths()).anyMatch(path -> path.matches(resourcePath))) {
                countInScope += 1;
                final boolean addToCache = isAllVanityPathEntriesCached()
                        || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries();
                String firstVanityPath = loadVanityPath(resource, resolveMapsMap, targetPaths, addToCache);
                if (supportsSort && firstVanityPath != null) {
                    if (previousVanityPath != null && firstVanityPath.compareTo(previousVanityPath) < 0) {
                        log.error("Sorting by first(vanityPath) does not appear to work; got " + firstVanityPath + " after " + previousVanityPath);
                    }
                    previousVanityPath = firstVanityPath;
               }
            }
        }
        long processElapsed = System.nanoTime() - processStart;
        log.debug("processed {} resources with sling:vanityPath properties (of which {} in scope) in {}ms", count, countInScope, TimeUnit.NANOSECONDS.toMillis(processElapsed));
        if (!isAllVanityPathEntriesCached()) {
            if (countInScope > this.factory.getMaxCachedVanityPathEntries()) {
                log.warn("Number of resources with sling:vanityPath property ({}) exceeds configured cache size ({}); handling of uncached vanity paths will be much slower. Consider increasing the cache size or decreasing the number of vanity paths.", countInScope, this.factory.getMaxCachedVanityPathEntries());
            } else if (countInScope > (this.factory.getMaxCachedVanityPathEntries() / 10) * 9) {
                log.info("Number of resources with sling:vanityPath property in scope ({}) within 10% of configured cache size ({})", countInScope, this.factory.getMaxCachedVanityPathEntries());
            }
        }

        this.vanityResourcesOnStartup.set(count);

        return targetPaths;
    }

    /**
     * Load vanity path given a resource
     * 
     * @return first vanity path or {@code null}
     */
    private String loadVanityPath(final Resource resource, final Map<String, List<MapEntry>> entryMap, final Map <String, List<String>> targetPaths, boolean addToCache) {

        if (!isValidVanityPath(resource.getPath())) {
            return null;
        }

        final ValueMap props = resource.getValueMap();
        long vanityOrder = props.get(PROP_VANITY_ORDER, 0L);

        // url is ignoring scheme and host.port and the path is
        // what is stored in the sling:vanityPath property
        boolean hasVanityPath = false;
        final String[] pVanityPaths = props.get(PROP_VANITY_PATH, new String[0]);
        if (log.isTraceEnabled()) {
            log.trace("vanity paths on {}: {}", resource.getPath(), Arrays.asList(pVanityPaths));
        }

        for (final String pVanityPath : pVanityPaths) {
            final String[] result = this.getVanityPathDefinition(resource.getPath(), pVanityPath);
            if (result != null) {
                hasVanityPath = true;
                final String url = result[0] + result[1];
                // redirect target is the node providing the
                // sling:vanityPath
                // property (or its parent if the node is called
                // jcr:content)
                final Resource redirectTarget;
                if (JCR_CONTENT.equals(resource.getName())) {
                    redirectTarget = resource.getParent();
                } else {
                    redirectTarget = resource;
                }
                final String redirect = redirectTarget.getPath();
                final String redirectName = redirectTarget.getName();

                // whether the target is attained by a external redirect or
                // by an internal redirect is defined by the sling:redirect
                // property
                final int status = props.get(PROP_REDIRECT_EXTERNAL, false) ? props.get(
                        PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS, factory.getDefaultVanityPathRedirectStatus())
                        : -1;

                final String checkPath = result[1];

                boolean addedEntry;
                if (addToCache) {
                    if (redirectName.indexOf('.') > -1) {
                        // 1. entry with exact match
                        this.addEntry(entryMap, checkPath, getMapEntry(url + "$", status, false, vanityOrder, redirect));

                        final int idx = redirectName.lastIndexOf('.');
                        final String extension = redirectName.substring(idx + 1);

                        // 2. entry with extension
                        addedEntry = this.addEntry(entryMap, checkPath, getMapEntry(url + "\\." + extension, status, false, vanityOrder, redirect));
                    } else {
                        // 1. entry with exact match
                        this.addEntry(entryMap, checkPath, getMapEntry(url + "$", status, false, vanityOrder, redirect + ".html"));

                        // 2. entry with match supporting selectors and extension
                        addedEntry = this.addEntry(entryMap, checkPath, getMapEntry(url + "(\\..*)", status, false, vanityOrder, redirect + "$1"));
                    }
                    if (addedEntry) {
                        // 3. keep the path to return
                        this.updateTargetPaths(targetPaths, redirect, checkPath);
                        //increment only if the instance variable
                        if (entryMap == resolveMapsMap) {
                            vanityCounter.addAndGet(2);
                        }

                        // update bloom filter
                        BloomFilterUtils.add(vanityBloomFilter, checkPath);
                    }
                } else {
                    // update bloom filter
                    BloomFilterUtils.add(vanityBloomFilter, checkPath);
                }
            }
        }
        return hasVanityPath ? pVanityPaths[0] : null;
    }

    private void updateTargetPaths(final Map<String, List<String>> targetPaths, final String key, final String entry) {
        if (entry == null) {
           return;
        }
        List<String> entries = targetPaths.get(key);
        if (entries == null) {
            entries = new ArrayList<>();
            targetPaths.put(key, entries);
        }
        entries.add(entry);
    }

    /**
     * Create the vanity path definition. String array containing:
     * {protocol}/{host}[.port] {absolute path}
     */
    private String[] getVanityPathDefinition(final String sourcePath, final String vanityPath) {

        if (vanityPath == null) {
            log.trace("getVanityPathDefinition: null vanity path on {}", sourcePath);
            return null;
        }

        String info = vanityPath.trim();

        if (info.isEmpty()) {
            log.trace("getVanityPathDefinition: empty vanity path on {}", sourcePath);
            return null;
        }

        String prefix = null;
        String path = null;

        // check for URL-shaped path
        if (info.indexOf(":/") > -1) {
            try {
                final URL u = new URL(info);
                prefix = u.getProtocol() + '/' + u.getHost() + '.' + u.getPort();
                path = u.getPath();
            } catch (final MalformedURLException e) {
                log.warn("Ignoring malformed vanity path '{}' on {}", info, sourcePath);
                return null;
            }
        } else {
            prefix = "^" + ANY_SCHEME_HOST;

            if (!info.startsWith("/")) {
                path = "/" + info;
            } else {
                path = info;
            }
        }

        // remove extension
        int lastSlash = path.lastIndexOf('/');
        int firstDot = path.indexOf('.', lastSlash + 1);
        if (firstDot != -1) {
            path = path.substring(0, firstDot);
            log.warn("Removing extension from vanity path '{}' on {}", info, sourcePath);
        }

        return new String[] { prefix, path };
    }

    private void loadConfiguration(final MapConfigurationProvider factory, final List<MapEntry> entries) {
        // virtual uris
        final Map<String, String> virtuals = factory.getVirtualURLMap();
        if (virtuals != null) {
            for (final Entry<String, String> virtualEntry : virtuals.entrySet()) {
                final String extPath = virtualEntry.getKey();
                final String intPath = virtualEntry.getValue();
                if (!extPath.equals(intPath)) {
                    // this regular expression must match the whole URL !!
                    final String url = "^" + ANY_SCHEME_HOST + extPath + "$";
                    final String redirect = intPath;
                    MapEntry mapEntry = getMapEntry(url, -1, false, redirect);
                    if (mapEntry!=null){
                        entries.add(mapEntry);
                    }
                }
            }
        }

        // URL Mappings
        final Mapping[] mappings = factory.getMappings();
        if (mappings != null) {
            final Map<String, List<String>> map = new HashMap<>();
            for (final Mapping mapping : mappings) {
                if (mapping.mapsInbound()) {
                    final String url = mapping.getTo();
                    final String alias = mapping.getFrom();
                    if (url.length() > 0) {
                        List<String> aliasList = map.get(url);
                        if (aliasList == null) {
                            aliasList = new ArrayList<>();
                            map.put(url, aliasList);
                        }
                        aliasList.add(alias);
                    }
                }
            }

            for (final Entry<String, List<String>> entry : map.entrySet()) {
                MapEntry mapEntry = getMapEntry(ANY_SCHEME_HOST + entry.getKey(), -1, false, entry.getValue().toArray(new String[0]));
                if (mapEntry!=null){
                    entries.add(mapEntry);
                }
            }
        }
    }

    private void loadMapConfiguration(final MapConfigurationProvider factory, final Map<String, MapEntry> entries) {
        // URL Mappings
        final Mapping[] mappings = factory.getMappings();
        if (mappings != null) {
            for (int i = mappings.length - 1; i >= 0; i--) {
                final Mapping mapping = mappings[i];
                if (mapping.mapsOutbound()) {
                    final String url = mapping.getTo();
                    final String alias = mapping.getFrom();
                    if (!url.equals(alias)) {
                        addMapEntry(entries, alias, url, -1);
                    }
                }
            }
        }

        // virtual uris
        final Map<String, String> virtuals = factory.getVirtualURLMap();
        if (virtuals != null) {
            for (final Entry<String, String> virtualEntry : virtuals.entrySet()) {
                final String extPath = virtualEntry.getKey();
                final String intPath = virtualEntry.getValue();
                if (!extPath.equals(intPath)) {
                    // this regular expression must match the whole URL !!
                    final String path = "^" + intPath + "$";
                    final String url = extPath;
                    addMapEntry(entries, path, url, -1);
                }
            }
        }
    }

    private void addMapEntry(final Map<String, MapEntry> entries, final String path, final String url, final int status) {
        MapEntry entry = entries.get(path);
        if (entry == null) {
            entry = getMapEntry(path, status, false, url);
        } else {
            final String[] redir = entry.getRedirect();
            final String[] newRedir = new String[redir.length + 1];
            System.arraycopy(redir, 0, newRedir, 0, redir.length);
            newRedir[redir.length] = url;
            entry = getMapEntry(entry.getPattern(), entry.getStatus(), false, newRedir);
        }
        if (entry!=null){
            entries.put(path, entry);
        }
    }

    private final AtomicLong lastTimeLogged = new AtomicLong(-1);

    private final long LOGGING_ERROR_PERIOD = 1000 * 60 * 5;

    @Override
    public void logDisableAliasOptimization() {
        this.logDisableAliasOptimization(null);
    }

    private void logDisableAliasOptimization(final Exception e) {
        if ( e != null ) {
            log.error("Unexpected problem during initialization of optimize alias resolution. Therefore disabling optimize alias resolution. Please fix the problem.", e);
        } else {
            final long now = System.currentTimeMillis();
            if ( now - lastTimeLogged.getAndSet(now) > LOGGING_ERROR_PERIOD) {
                log.error("A problem occured during initialization of optimize alias resolution. Optimize alias resolution is disabled. Check the logs for the reported problem.", e);
            }
        }

    }

    private final class MapEntryIterator implements Iterator<MapEntry> {

        private final Map<String, List<MapEntry>> resolveMapsMap;

        private String key;

        private MapEntry next;

        private final Iterator<MapEntry> globalListIterator;
        private MapEntry nextGlobal;

        private Iterator<MapEntry> specialIterator;
        private MapEntry nextSpecial;

        private boolean vanityPathPrecedence;

        public MapEntryIterator(final String startKey, final Map<String, List<MapEntry>> resolveMapsMap, final boolean vanityPathPrecedence) {
            this.key = startKey;
            this.resolveMapsMap = resolveMapsMap;
            this.globalListIterator = this.resolveMapsMap.get(GLOBAL_LIST_KEY).iterator();
            this.vanityPathPrecedence = vanityPathPrecedence;
            this.seek();
        }

        /**
         * @see java.util.Iterator#hasNext()
         */
        @Override
        public boolean hasNext() {
            return this.next != null;
        }

        /**
         * @see java.util.Iterator#next()
         */
        @Override
        public MapEntry next() {
            if (this.next == null) {
                throw new NoSuchElementException();
            }
            final MapEntry result = this.next;
            this.seek();
            return result;
        }

        /**
         * @see java.util.Iterator#remove()
         */
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        private void seek() {
            if (this.nextGlobal == null && this.globalListIterator.hasNext()) {
                this.nextGlobal = this.globalListIterator.next();
            }
            if (this.nextSpecial == null) {
                if (specialIterator != null && !specialIterator.hasNext()) {
                    specialIterator = null;
                }
                while (specialIterator == null && key != null) {
                    // remove selectors and extension
                    final int lastSlashPos = key.lastIndexOf('/');
                    final int lastDotPos = key.indexOf('.', lastSlashPos);
                    if (lastDotPos != -1) {
                        key = key.substring(0, lastDotPos);
                    }

                    final List<MapEntry> special;
                    if (MapEntries.this.isAllVanityPathEntriesCached() && MapEntries.this.vanityPathsProcessed.get()) {
                        special = this.resolveMapsMap.get(key);
                    } else {
                        special = MapEntries.this.getMapEntryList(key); 
                    }
                    if (special != null) {
                        specialIterator = special.iterator();
                    }
                    // recurse to the parent
                    if (key.length() > 1) {
                        final int lastSlash = key.lastIndexOf("/");
                        if (lastSlash == 0) {
                            key = null;
                        } else {
                            key = key.substring(0, lastSlash);
                        }
                    } else {
                        key = null;
                    }
                }
                if (this.specialIterator != null && this.specialIterator.hasNext()) {
                    this.nextSpecial = this.specialIterator.next();
                }
            }
            if (this.nextSpecial == null) {
                this.next = this.nextGlobal;
                this.nextGlobal = null;
            } else if (!this.vanityPathPrecedence){
                if (this.nextGlobal == null) {
                    this.next = this.nextSpecial;
                    this.nextSpecial = null;
                } else if (this.nextGlobal.getPattern().length() >= this.nextSpecial.getPattern().length()) {
                    this.next = this.nextGlobal;
                    this.nextGlobal = null;

                }else {
                    this.next = this.nextSpecial;
                    this.nextSpecial = null;
                }
            } else {
                this.next = this.nextSpecial;
                this.nextSpecial = null;
            }
        }
    };

    private MapEntry getMapEntry(String url, final int status, final boolean trailingSlash,
            final String... redirect){

        MapEntry mapEntry = null;
        try{
            mapEntry = new MapEntry(url, status, trailingSlash, 0, redirect);
        }catch (IllegalArgumentException iae){
            //ignore this entry
            log.debug("ignored entry due exception ",iae);
        }
        return mapEntry;
    }

    private MapEntry getMapEntry(String url, final int status, final boolean trailingSlash, long order,
            final String... redirect){

        MapEntry mapEntry = null;
        try{
            mapEntry = new MapEntry(url, status, trailingSlash, order, redirect);
        }catch (IllegalArgumentException iae){
            //ignore this entry
            log.debug("ignored entry due exception ",iae);
        }
        return mapEntry;
    }
}
