/*
 * 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 java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
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.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingException;
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.ResourceResolverFactoryImpl;
import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
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;

public class MapEntries implements
    MapEntriesHandler,
    ResourceChangeListener,
    ExternalResourceChangeListener,
    AutoCloseable {

    private static final String JCR_CONTENT = "jcr:content";
    private static final int TRAVERSAL_RETRY_INTERVAL = 30000;

    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 String VANITY_BLOOM_FILTER_NAME = "vanityBloomFilter.txt";

    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;

    private static final String JCR_SYSTEM_PREFIX = "/jcr:system/";

    final static String ALIAS_QUERY_DEFAULT = "SELECT sling:alias FROM nt:base WHERE sling:alias IS NOT NULL";

    final static String ALIAS_QUERY_NO_TRAVERSAL = ALIAS_QUERY_DEFAULT + " option(traversal fail)";

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

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

    private volatile MapConfigurationProvider factory;

    private volatile ResourceResolver resolver;

    private volatile EventAdmin eventAdmin;

    private volatile ServiceRegistration<ResourceChangeListener> registration;

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

    private Collection<MapEntry> mapMaps;

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

    private volatile Map<String, Map<String, String>> aliasMap;

    private final ReentrantLock initializing = new ReentrantLock();

    private final AtomicLong vanityCounter;

    private final File vanityBloomFilterFile;

    private byte[] vanityBloomFilter;

    private Timer timer;

    private boolean updateBloomFilterFile = false;

    private Thread aliasTraversal = null;

    @SuppressWarnings({ "unchecked" })
    public MapEntries(final MapConfigurationProvider factory, final BundleContext bundleContext, final EventAdmin eventAdmin)
        throws LoginException, IOException {

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

        this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, (List<MapEntry>)Collections.EMPTY_LIST);
        this.mapMaps = Collections.<MapEntry> emptyList();
        this.vanityTargets = Collections.<String,List <String>>emptyMap();
        this.aliasMap = Collections.emptyMap();

        doInit();

        final Dictionary<String, Object> props = new Hashtable<>();
        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);
        log.info("Registering for {}", Arrays.toString(factory.getObservationPaths()));
        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Map Entries Observation");
        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
        this.registration = bundleContext.registerService(ResourceChangeListener.class, this, props);

        this.vanityCounter = new AtomicLong(0);
        this.vanityBloomFilterFile = bundleContext.getDataFile(VANITY_BLOOM_FILTER_NAME);
        initializeVanityPaths();
    }

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

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

            final Map<String, List<MapEntry>> newResolveMapsMap = new ConcurrentHashMap<>();

            aliasMap = Collections.emptyMap();
            //optimization made in SLING-2521
            if (this.factory.isOptimizeAliasResolutionEnabled()) {
		aliasTraversal = new Thread(new Runnable(){
				public void run() {
					aliasMap = loadAliases(resolver);
					}
				});
		aliasTraversal.start();
            }

            this.resolveMapsMap = newResolveMapsMap;

            doUpdateConfiguration();

            sendChangeEvent();
        } catch (final Exception e) {

            log.warn("doInit: Unexpected problem during initialization", e);

        } 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()) {

                if (vanityBloomFilterFile == null) {
                    throw new RuntimeException(
                            "This platform does not have file system support");
                }
                boolean createVanityBloomFilter = false;
                if (!vanityBloomFilterFile.exists()) {
                    log.debug("creating bloom filter file {}",
                            vanityBloomFilterFile.getAbsolutePath());
                    vanityBloomFilter = createVanityBloomFilter();
                    persistBloomFilter();
                    createVanityBloomFilter = true;
                } else {
                    // initialize bloom filter from disk
                    vanityBloomFilter = new byte[(int) vanityBloomFilterFile
                            .length()];
                    DataInputStream dis = new DataInputStream(
                            new FileInputStream(vanityBloomFilterFile));
                    try {
                        dis.readFully(vanityBloomFilter);
                    } finally {
                        dis.close();
                    }
                }

                // task for persisting the bloom filter every minute (if changes
                // exist)
                timer = new Timer();
                timer.schedule(new BloomFilterTask(), 60 * 1000);

                final Map<String, List<String>> vanityTargets = this
                        .loadVanityPaths(createVanityBloomFilter);
                this.vanityTargets = vanityTargets;
            }
        } finally {
            this.initializing.unlock();
        }

    }

    protected int getTraversalRetryInterval(){
	return TRAVERSAL_RETRY_INTERVAL;
    }

    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.factory.isOptimizeAliasResolutionEnabled() && 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.factory.isOptimizeAliasResolutionEnabled() || 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.factory.isOptimizeAliasResolutionEnabled()) {
                        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.factory.isOptimizeAliasResolutionEnabled()) {
            for (final String contentPath : this.aliasMap.keySet()) {
                if (path.startsWith(contentPath + "/") || path.equals(contentPath)) {
                    changed |= removeAlias(contentPath, path, resolverRefreshed);
                } else if ( contentPath.startsWith(actualContentPathPrefix) ) {
                    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
     * @param refreshed Flag if session needs refresh
     * @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;
        String resourcePath = null;
        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;
            }
        }
        else {
            resourcePath = contentPath;
        }
        if ( !handle ) {
            return false;
        }

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

                for (Iterator<Map.Entry<String, String>> iterator = aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) {
                    final Map.Entry<String, String> entry = iterator.next();
                    String prefix = contentPath.endsWith("/") ? contentPath : contentPath + "/";
                    if ((prefix + entry.getValue()).startsWith(resourcePath)){
                        iterator.remove();
                    }
                }

                if (aliasMapEntry.isEmpty()) {
                    this.aliasMap.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 needsUpdate = false;
        if (isAllVanityPathEntriesCached() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries()) {
            // fill up the cache and the bloom filter
            needsUpdate = loadVanityPath(resource, resolveMapsMap, vanityTargets, true, true);
        } else {
            // fill up the bloom filter
            needsUpdate = loadVanityPath(resource, resolveMapsMap, vanityTargets, false, true);
        }
        if ( needsUpdate ) {
            updateBloomFilterFile = true;
            return true;
        }
        return false;
    }

    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.aliasMap);
    }

    /**
     * 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, String> aliasMapEntry = parentPath == null ? null : aliasMap.get(parentPath);
            if (aliasMapEntry != null) {
                for (Iterator<Map.Entry<String, String>> iterator = aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) {
                    final Map.Entry<String, String> entry = iterator.next();
                    if (containingResourceName.equals(entry.getValue())){
                        iterator.remove();
                    }
                }
            }

            if (aliasMapEntry != null && aliasMapEntry.isEmpty()) {
                this.aliasMap.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() {
        try {
            persistBloomFilter();
        } catch (IOException e) {
           log.error("Error while saving bloom filter to disk", e);
        }

        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;
    }

    /**
     * This is for the web console plugin
     */
    @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);
    }

    /**
     * Calculate the resolve maps. As the entries have to be sorted by pattern
     * length, we have to create a new list containing all relevant 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;
    }

    @Override
    public Map<String, String> getAliasMap(final String parentPath) {
        return aliasMap.get(parentPath);
    }

	@Override
	public boolean isAliasMapInitialized() {
		// since loading the aliases is equivalent to replacing the empty map
		// with another instance, and the reference is volatile, it's safe
		// to equate initialization being done with the empty map being replaced
		// note that it's not provably safe to check the map size, as we might
		// enter the scenario where there are no aliases
		return aliasMap != Collections.<String,Map<String,String>> emptyMap();
	}

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

        if (BloomFilterUtils.probablyContains(vanityBloomFilter, vanityPath)) {
            mapEntries = this.resolveMapsMap.get(vanityPath);
            if (mapEntries == null) {
                Map<String, List<MapEntry>>  mapEntry = getVanityPaths(vanityPath);
                mapEntries = mapEntry.get(vanityPath);
            }
        }

        return 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(ResourceResolverFactoryImpl, BundleContext, EventAdmin)}
     * constructor makes sure the event listener is registered to only get
     * appropriate events.
     */
    @Override
    public void onChange(final List<ResourceChange> changes) {
        final AtomicBoolean resolverRefreshed = new AtomicBoolean(false);

        // the config needs to be reloaded only once
        final AtomicBoolean hasReloadedConfig = new AtomicBoolean(false);
        for(final ResourceChange rc : changes) {

            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;
            }

            boolean changed = false;
            // removal of a resource is handled differently
            if (rc.getType() == 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 (rc.getType() == 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 (rc.getType() == ResourceChange.ChangeType.CHANGED ) {

                final Boolean result = handleConfigurationUpdate(path, hasReloadedConfig, resolverRefreshed, false);
                if ( result != null ) {
                    if ( result ) {
                        changed = true;
                    } else {
                        changed |= updateResource(path, resolverRefreshed);
                    }
                }

            }

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

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

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

    private void persistBloomFilter() throws IOException {
        if (vanityBloomFilterFile != null && vanityBloomFilter != null) {
            FileOutputStream out = new FileOutputStream(vanityBloomFilterFile);
            try {
                out.write(this.vanityBloomFilter);
            } finally {
                out.close();
            }
        }
    }

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

    /**
     * Escapes illegal XPath search characters at the end of a string.
     * <p>
     * Example:<br>
     * A search string like 'test?' will run into a ParseException documented in
     * http://issues.apache.org/jira/browse/JCR-1248
     *
     * @param s
     *            the string to encode
     * @return the escaped string
     */
    private static String escapeIllegalXpathSearchChars(String s) {
        StringBuilder sb = new StringBuilder();
        if (s != null && s.length() > 1) {
            sb.append(s.substring(0, (s.length() - 1)));
            char c = s.charAt(s.length() - 1);
            // NOTE: keep this in sync with _ESCAPED_CHAR below!
            if (c == '!' || c == '(' || c == ':' || c == '^' || c == '['
                    || c == ']' || c == '{' || c == '}' || c == '?') {
                sb.append('\\');
            }
            sb.append(c);
        }
        return sb.toString();
    }

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

                // sling:vanityPath (lowercase) is the property name
        final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM nt:base WHERE sling:vanityPath ="
                + "'"+escapeIllegalXpathSearchChars(vanityPath).replaceAll("'", "''")+"' OR sling:vanityPath ="+ "'"+escapeIllegalXpathSearchChars(vanityPath.substring(1)).replaceAll("'", "''")+"' ORDER BY sling:vanityOrder DESC";

        ResourceResolver queryResolver = null;

        try {
            queryResolver = factory.getServiceResourceResolver(factory.getServiceUserAuthenticationInfo("mapping"));
            final Iterator<Resource> i = queryResolver.findResources(queryString, "sql");
            while (i.hasNext()) {
                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 ) {
                    if (this.factory.isMaxCachedVanityPathEntriesStartup() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries()) {
                        loadVanityPath(resource, resolveMapsMap, vanityTargets, true, false);
                        entryMap = resolveMapsMap;
                    } else {
                        final Map <String, List<String>> targetPaths = new HashMap <>();
                        loadVanityPath(resource, entryMap, targetPaths, true, false);
                    }
                }
            }
        } catch (LoginException e) {
            log.error("Exception while obtaining queryResolver", e);
        } finally {
            if (queryResolver != null) {
                queryResolver.close();
            }
        }
        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 white 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 white 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;
            }

            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){
            return false;
        }

        List<MapEntry> entries = entryMap.get(key);
        if (entries == null) {
            entries = new ArrayList<>();
            entries.add(entry);
            // and finally sort list
            Collections.sort(entries);
            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);
        }
        return true;
    }

    /**
     * Load aliases Search for all nodes inheriting the sling:alias
     * property
     */
    private Map<String, Map<String, String>> loadAliases(final ResourceResolver resolver) {
        final Map<String, Map<String, String>> map = new ConcurrentHashMap<>();
		String queryString = this.factory.isForceNoAliasTraversal() ? ALIAS_QUERY_NO_TRAVERSAL : ALIAS_QUERY_DEFAULT;
		while (true){
	        try {
		        final Iterator<Resource> i = resolver.findResources(queryString, "sql");
		        while (i.hasNext()) {
		            final Resource resource = i.next();
		            loadAlias(resource, map);
		        }
		        break;
		} catch (SlingException e) {
			Throwable cause = unwrapThrowable(e);
			if (cause instanceof IllegalArgumentException && ALIAS_QUERY_NO_TRAVERSAL.equals(queryString)) {
					log.debug(
						"Expected index not available yet - will retry", e);
					try {
						TimeUnit.MILLISECONDS.sleep(getTraversalRetryInterval());
					} catch (InterruptedException ex) {
						log.warn("Interrupted while sleeping", ex);
					}
				} else if (cause instanceof ParseException) {
				if (ALIAS_QUERY_NO_TRAVERSAL.equals(queryString)) {
						log.warn("Traversal fail option set but query not accepted by queryengine, falling back to allowing traversal as queryengine might not support option", e);
						queryString = ALIAS_QUERY_DEFAULT;
					} else {
						log.error("Queryengine couldn't parse query - interrupting loading of aliasmap",e);
						break;
					}
					try {
						TimeUnit.MILLISECONDS.sleep(getTraversalRetryInterval());
					} catch (InterruptedException ex) {
						log.warn("Interrupted while sleeping", ex);
					}


				} else {
					log.error("QueryEngine not able to process query {} ", queryString, e);
					break;
				}
		}
		}
        return map;
    }

    /**
     * Extract root cause of exception
     * @param e {@code Throwable} to be checked
     * @return Root {@code Throwable}
     */
    private Throwable unwrapThrowable(Throwable e) {
		return e.getCause() == null ? e : unwrapThrowable(e.getCause());
	}

	/**
     * Load alias given a resource
     */
    private boolean loadAlias(final Resource resource, Map<String, Map<String, String>> map) {
        // ignore system tree
        if (resource.getPath().startsWith(JCR_SYSTEM_PREFIX)) {
            log.debug("loadAliases: Ignoring {}", resource);
            return false;
        }

        final String resourceName;
        final String parentPath;
        if (JCR_CONTENT.equals(resource.getName())) {
            final Resource containingResource = resource.getParent();
            if ( containingResource != null ) {
                final Resource parent = containingResource.getParent();
                if ( parent != null ) {
                    parentPath = parent.getPath();
                    resourceName = containingResource.getName();
                } else {
                    parentPath = null;
                    resourceName = null;
                }
            } else {
                parentPath = null;
                resourceName = null;
            }
        } else {
            final Resource parent = resource.getParent();
            if ( parent != null ) {
                parentPath = parent.getPath();
                resourceName = resource.getName();
            } else {
                parentPath = null;
                resourceName = null;
            }
        }
        boolean hasAlias = false;
        if ( parentPath != null ) {
            // require properties
            final ValueMap props = resource.getValueMap();
            final String[] aliasArray = props.get(ResourceResolverImpl.PROP_ALIAS, String[].class);

            if ( aliasArray != null ) {
                Map<String, String> parentMap = map.get(parentPath);
                for (final String alias : aliasArray) {
                    if (parentMap != null && parentMap.containsKey(alias)) {
                        log.warn("Encountered duplicate alias {} under parent path {}. Refusing to replace current target {} with {}.", new Object[] {
                                alias,
                                parentPath,
                                parentMap.get(alias),
                                resourceName
                        });
                    } else {
                        // check 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;
                                }
                            }
                        }
                        if ( invalid ) {
                            log.warn("Encountered invalid alias {} under parent path {}. Refusing to use it.",
                                    alias, parentPath);
                        } else {
                            if (parentMap == null) {
                                parentMap = new LinkedHashMap<>();
                                map.put(parentPath, parentMap);
                            }
                            parentMap.put(alias, resourceName);
                            hasAlias = true;
                        }
                    }
                }
            }
        }
        return hasAlias;
    }

    /**
     * Load vanity paths Search for all nodes inheriting the sling:VanityPath
     * mixin
     */
    private Map <String, List<String>> loadVanityPaths(boolean createVanityBloomFilter) {
        // sling:vanityPath (lowercase) is the property name
        final Map <String, List<String>> targetPaths = new ConcurrentHashMap <>();
        final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM nt:base WHERE sling:vanityPath IS NOT NULL";
        final Iterator<Resource> i = resolver.findResources(queryString, "sql");

        while (i.hasNext() && (createVanityBloomFilter || isAllVanityPathEntriesCached() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries())) {
            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 ) {
                if (isAllVanityPathEntriesCached() || vanityCounter.longValue() < this.factory.getMaxCachedVanityPathEntries()) {
                    // fill up the cache and the bloom filter
                    loadVanityPath(resource, resolveMapsMap, targetPaths, true,
                            createVanityBloomFilter);
                } else {
                    // fill up the bloom filter
                    loadVanityPath(resource, resolveMapsMap, targetPaths, false,
                            createVanityBloomFilter);
                }
            }

        }


        return targetPaths;
    }

    /**
     * Load vanity path given a resource
     */
    private boolean loadVanityPath(final Resource resource, final Map<String, List<MapEntry>> entryMap, final Map <String, List<String>> targetPaths, boolean addToCache, boolean newVanity) {

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

        final ValueMap props = resource.getValueMap();
        long vanityOrder = 0;
        if (props.containsKey(PROP_VANITY_ORDER)) {
            vanityOrder = props.get(PROP_VANITY_ORDER, Long.class);
        }

        // 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]);
        for (final String pVanityPath : pVanityPaths) {
            final String[] result = this.getVanityPathDefinition(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);
                        }

                        if (newVanity) {
                            // update bloom filter
                            BloomFilterUtils.add(vanityBloomFilter, checkPath);
                        }
                    }
                } else {
                    if (newVanity) {
                        // update bloom filter
                        BloomFilterUtils.add(vanityBloomFilter, checkPath);
                    }
                }
            }
        }
        return hasVanityPath;
    }

    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 pVanityPath) {
        String[] result = null;
        if (pVanityPath != null) {
            final String info = pVanityPath.trim();
            if (info.length() > 0) {
                String prefix = null;
                String path = null;
                // check for url
                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 {}", pVanityPath);
                    }
                } else {
                    prefix = "^" + ANY_SCHEME_HOST;
                    if (!info.startsWith("/")) {
                        path = "/" + info;
                    } else {
                        path = info;
                    }
                }

                // remove extension
                if (prefix != null) {
                    final int lastSlash = path.lastIndexOf('/');
                    final int firstDot = path.indexOf('.', lastSlash + 1);
                    if (firstDot != -1) {
                        path = path.substring(0, firstDot);
                        log.warn("Removing extension from vanity path {}", pVanityPath);
                    }
                    result = new String[] { prefix, path };
                }
            }
        }
        return result;
    }

    private void loadConfiguration(final MapConfigurationProvider factory, final List<MapEntry> entries) {
        // virtual uris
        final Map<?, ?> virtuals = factory.getVirtualURLMap();
        if (virtuals != null) {
            for (final Entry<?, ?> virtualEntry : virtuals.entrySet()) {
                final String extPath = (String) virtualEntry.getKey();
                final String intPath = (String) 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<?, ?> virtuals = factory.getVirtualURLMap();
        if (virtuals != null) {
            for (final Entry<?, ?> virtualEntry : virtuals.entrySet()) {
                final String extPath = (String) virtualEntry.getKey();
                final String intPath = (String) 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 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()) {
                        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;
    }

    final class BloomFilterTask extends TimerTask {
        @Override
        public void run() {
            try {
                if (updateBloomFilterFile) {
                    persistBloomFilter();
                    updateBloomFilterFile = false;
                }
            } catch (IOException e) {
                throw new RuntimeException(
                        "Error while saving bloom filter to disk", e);
            }
        }
    }

	@Override
	public void close() throws Exception {
		if (aliasTraversal != null) {
			aliasTraversal.interrupt();
		}
	}

}
