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

import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;
import org.apache.wiki.WikiBackgroundThread;
import org.apache.wiki.api.core.Acl;
import org.apache.wiki.api.core.AclEntry;
import org.apache.wiki.api.core.Attachment;
import org.apache.wiki.api.core.Context;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Page;
import org.apache.wiki.api.exceptions.NoRequiredPropertyException;
import org.apache.wiki.api.exceptions.ProviderException;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.api.providers.PageProvider;
import org.apache.wiki.api.providers.WikiProvider;
import org.apache.wiki.api.spi.Wiki;
import org.apache.wiki.attachment.AttachmentManager;
import org.apache.wiki.auth.WikiPrincipal;
import org.apache.wiki.auth.WikiSecurityException;
import org.apache.wiki.auth.acl.AclManager;
import org.apache.wiki.auth.user.UserProfile;
import org.apache.wiki.diff.DifferenceManager;
import org.apache.wiki.event.WikiEvent;
import org.apache.wiki.event.WikiEventManager;
import org.apache.wiki.event.WikiPageEvent;
import org.apache.wiki.event.WikiSecurityEvent;
import org.apache.wiki.providers.RepositoryModifiedException;
import org.apache.wiki.references.ReferenceManager;
import org.apache.wiki.search.SearchManager;
import org.apache.wiki.tasks.TasksManager;
import org.apache.wiki.ui.CommandResolver;
import org.apache.wiki.util.ClassUtil;
import org.apache.wiki.util.TextUtil;
import org.apache.wiki.workflow.Decision;
import org.apache.wiki.workflow.DecisionRequiredException;
import org.apache.wiki.workflow.Fact;
import org.apache.wiki.workflow.Step;
import org.apache.wiki.workflow.Workflow;
import org.apache.wiki.workflow.WorkflowBuilder;
import org.apache.wiki.workflow.WorkflowManager;

import java.io.IOException;
import java.security.Permission;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;


/**
 * Manages the WikiPages. This class functions as an unified interface towards the page providers. It handles initialization
 * and management of the providers, and provides utility methods for accessing the contents.
 * <p/>
 * Saving a page is a two-stage Task; first the pre-save operations and then the actual save. See the descriptions of the tasks
 * for further information.
 *
 * @since 2.0
 */
public class DefaultPageManager implements PageManager {

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

    private PageProvider m_provider;

    private Engine m_engine;

    protected ConcurrentHashMap< String, PageLock > m_pageLocks = new ConcurrentHashMap<>();

    private int m_expiryTime;

    private LockReaper m_reaper = null;

    private PageSorter pageSorter = new PageSorter();

    /**
     * Creates a new PageManager.
     *
     * @param engine Engine instance
     * @param props  Properties to use for initialization
     * @throws NoSuchElementException {@value #PROP_PAGEPROVIDER} property not found on Engine properties
     * @throws WikiException If anything goes wrong, you get this.
     */
    public DefaultPageManager(final Engine engine, final Properties props) throws NoSuchElementException, WikiException {
        m_engine = engine;
        final String classname;
        final boolean useCache = "true".equals( props.getProperty( PROP_USECACHE ) );
        m_expiryTime = TextUtil.parseIntParameter( props.getProperty( PROP_LOCKEXPIRY ), 60 );

        //  If user wants to use a cache, then we'll use the CachingProvider.
        if( useCache ) {
            classname = "org.apache.wiki.providers.CachingProvider";
        } else {
            classname = TextUtil.getRequiredProperty( props, PROP_PAGEPROVIDER );
        }

        pageSorter.initialize( props );

        try {
            LOG.debug("Page provider class: '" + classname + "'");
            final Class<?> providerclass = ClassUtil.findClass("org.apache.wiki.providers", classname);
            m_provider = ( PageProvider ) providerclass.newInstance();

            LOG.debug("Initializing page provider class " + m_provider);
            m_provider.initialize(m_engine, props);
        } catch (final ClassNotFoundException e) {
            LOG.error("Unable to locate provider class '" + classname + "' (" + e.getMessage() + ")", e);
            throw new WikiException("No provider class. (" + e.getMessage() + ")", e);
        } catch (final InstantiationException e) {
            LOG.error("Unable to create provider class '" + classname + "' (" + e.getMessage() + ")", e);
            throw new WikiException("Faulty provider class. (" + e.getMessage() + ")", e);
        } catch (final IllegalAccessException e) {
            LOG.error("Illegal access to provider class '" + classname + "' (" + e.getMessage() + ")", e);
            throw new WikiException("Illegal provider class. (" + e.getMessage() + ")", e);
        } catch (final NoRequiredPropertyException e) {
            LOG.error("Provider did not found a property it was looking for: " + e.getMessage(), e);
            throw e;  // Same exception works.
        } catch (final IOException e) {
            LOG.error("An I/O exception occurred while trying to create a new page provider: " + classname, e);
            throw new WikiException("Unable to start page provider: " + e.getMessage(), e);
        }

    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getProvider()
     */
    @Override
    public PageProvider getProvider() {
        return m_provider;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getAllPages()
     */
    @Override
    public Collection< Page > getAllPages() throws ProviderException {
        return m_provider.getAllPages();
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPageText(java.lang.String, int)
     */
    @Override
    public String getPageText( final String pageName, final int version ) throws ProviderException {
        if (pageName == null || pageName.length() == 0) {
            throw new ProviderException( "Illegal page name" );
        }
        String text;

        try {
            text = m_provider.getPageText( pageName, version );
        } catch ( final RepositoryModifiedException e ) {
            //  This only occurs with the latest version.
            LOG.info( "Repository has been modified externally while fetching page " + pageName );

            //  Empty the references and yay, it shall be recalculated
            final Page p = m_provider.getPageInfo( pageName, version );

            m_engine.getManager( ReferenceManager.class ).updateReferences( p );
            m_engine.getManager( SearchManager.class ).reindexPage( p );
            text = m_provider.getPageText( pageName, version );
        }

        return text;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPureText(String, int)
     */
    @Override
    public String getPureText( final String page, final int version ) {
        String result = null;
        try {
            result = getPageText( page, version );
        } catch( final ProviderException e ) {
            LOG.error( "ProviderException getPureText for page " + page + " [version " + version + "]", e );
        } finally {
            if( result == null ) {
                result = "";
            }
        }
        return result;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getText(String, int)
     */
    @Override
    public String getText( final String page, final int version ) {
        final String result = getPureText( page, version );
        return TextUtil.replaceEntities( result );
    }

    @Override
    public void saveText( final Context context, final String text ) throws WikiException {
        // Check if page data actually changed; bail if not
        final Page page = context.getPage();
        final String oldText = getPureText( page );
        final String proposedText = TextUtil.normalizePostData( text );
        if ( oldText != null && oldText.equals( proposedText ) ) {
            return;
        }

        // Check if creation of empty pages is allowed; bail if not
        final boolean allowEmpty = TextUtil.getBooleanProperty( m_engine.getWikiProperties(),
                                                                Engine.PROP_ALLOW_CREATION_OF_EMPTY_PAGES,
                                                         false );
        if ( !allowEmpty && !wikiPageExists( page ) && text.trim().equals( "" ) ) {
            return;
        }

        // Create approval workflow for page save; add the diffed, proposed and old text versions as
        // Facts for the approver (if approval is required). If submitter is authenticated, any reject
        // messages will appear in his/her workflow inbox.
        final WorkflowBuilder builder = WorkflowBuilder.getBuilder( m_engine );
        final Principal submitter = context.getCurrentUser();
        final Step prepTask = m_engine.getManager( TasksManager.class ).buildPreSaveWikiPageTask( context, proposedText );
        final Step completionTask = m_engine.getManager( TasksManager.class ).buildSaveWikiPageTask();
        final String diffText = m_engine.getManager( DifferenceManager.class ).makeDiff( context, oldText, proposedText );
        final boolean isAuthenticated = context.getWikiSession().isAuthenticated();
        final Fact[] facts = new Fact[ 5 ];
        facts[ 0 ] = new Fact( WorkflowManager.WF_WP_SAVE_FACT_PAGE_NAME, page.getName() );
        facts[ 1 ] = new Fact( WorkflowManager.WF_WP_SAVE_FACT_DIFF_TEXT, diffText );
        facts[ 2 ] = new Fact( WorkflowManager.WF_WP_SAVE_FACT_PROPOSED_TEXT, proposedText );
        facts[ 3 ] = new Fact( WorkflowManager.WF_WP_SAVE_FACT_CURRENT_TEXT, oldText);
        facts[ 4 ] = new Fact( WorkflowManager.WF_WP_SAVE_FACT_IS_AUTHENTICATED, isAuthenticated );
        final String rejectKey = isAuthenticated ? WorkflowManager.WF_WP_SAVE_REJECT_MESSAGE_KEY : null;
        final Workflow workflow = builder.buildApprovalWorkflow( submitter,
                                                                 WorkflowManager.WF_WP_SAVE_APPROVER,
                                                                 prepTask,
                                                                 WorkflowManager.WF_WP_SAVE_DECISION_MESSAGE_KEY,
                                                                 facts,
                                                                 completionTask,
                                                                 rejectKey );
        m_engine.getManager( WorkflowManager.class ).start( workflow );

        // Let callers know if the page-save requires approval
        if ( workflow.getCurrentStep() instanceof Decision ) {
            throw new DecisionRequiredException( "The page contents must be approved before they become active." );
        }
    }

    /**
     * Returns the Engine to which this PageManager belongs to.
     *
     * @return The Engine object.
     */
    protected Engine getEngine() {
        return m_engine;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#putPageText(org.apache.wiki.api.core.Page, java.lang.String)
     */
    @Override
    public void putPageText( final Page page, final String content ) throws ProviderException {
        if (page == null || page.getName() == null || page.getName().length() == 0) {
            throw new ProviderException("Illegal page name");
        }

        m_provider.putPageText(page, content);
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#lockPage(org.apache.wiki.api.core.Page, java.lang.String)
     */
    @Override
    public PageLock lockPage( final Page page, final String user ) {
        if( m_reaper == null ) {
            //  Start the lock reaper lazily.  We don't want to start it in the constructor, because starting threads in constructors
            //  is a bad idea when it comes to inheritance.  Besides, laziness is a virtue.
            m_reaper = new LockReaper( m_engine );
            m_reaper.start();
        }

        fireEvent( WikiPageEvent.PAGE_LOCK, page.getName() ); // prior to or after actual lock?
        PageLock lock = m_pageLocks.get( page.getName() );

        if( lock == null ) {
            //
            //  Lock is available, so make a lock.
            //
            final Date d = new Date();
            lock = new PageLock( page, user, d, new Date( d.getTime() + m_expiryTime * 60 * 1000L ) );
            m_pageLocks.put( page.getName(), lock );
            LOG.debug( "Locked page " + page.getName() + " for " + user );
        } else {
            LOG.debug( "Page " + page.getName() + " already locked by " + lock.getLocker() );
            lock = null; // Nothing to return
        }

        return lock;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#unlockPage(org.apache.wiki.pages.PageLock)
     */
    @Override
    public void unlockPage( final PageLock lock ) {
        if (lock == null) {
            return;
        }

        m_pageLocks.remove( lock.getPage() );
        LOG.debug( "Unlocked page " + lock.getPage() );

        fireEvent( WikiPageEvent.PAGE_UNLOCK, lock.getPage() );
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getCurrentLock(org.apache.wiki.api.core.Page)
     */
    @Override
    public PageLock getCurrentLock( final Page page ) {
        return m_pageLocks.get( page.getName() );
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getActiveLocks()
     */
    @Override
    public List< PageLock > getActiveLocks() {
        return  new ArrayList<>( m_pageLocks.values() );
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPage(java.lang.String)
     */
    @Override
    public Page getPage( final String pagereq ) {
        return getPage( pagereq, PageProvider.LATEST_VERSION );
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPage(java.lang.String, int)
     */
    @Override
    public Page getPage( final String pagereq, final int version ) {
        try {
            Page p = getPageInfo( pagereq, version );
            if( p == null ) {
                p = m_engine.getManager( AttachmentManager.class ).getAttachmentInfo( null, pagereq );
            }

            return p;
        } catch( final ProviderException e ) {
            LOG.error( "Unable to fetch page info for " + pagereq + " [version " + version + "]", e );
            return null;
        }
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPageInfo(java.lang.String, int)
     */
    @Override
    public Page getPageInfo( final String pageName, final int version) throws ProviderException {
        if( pageName == null || pageName.length() == 0 ) {
            throw new ProviderException( "Illegal page name '" + pageName + "'" );
        }

        Page page;

        try {
            page = m_provider.getPageInfo( pageName, version );
        } catch( final RepositoryModifiedException e ) {
            //  This only occurs with the latest version.
            LOG.info( "Repository has been modified externally while fetching info for " + pageName );
            page = m_provider.getPageInfo( pageName, version );
            if( page != null ) {
                m_engine.getManager( ReferenceManager.class ).updateReferences( page );
            } else {
                m_engine.getManager( ReferenceManager.class ).pageRemoved( Wiki.contents().page( m_engine, pageName ) );
            }
        }

        return page;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getVersionHistory(java.lang.String)
     */
    @Override @SuppressWarnings( "unchecked" )
    public < T extends Page > List< T > getVersionHistory( final String pageName ) {
        List< T > c = null;

        try {
            if( pageExists( pageName ) ) {
                c = ( List< T > )m_provider.getVersionHistory( pageName );
            }

            if( c == null ) {
                c = ( List< T > )m_engine.getManager( AttachmentManager.class ).getVersionHistory( pageName );
            }
        } catch( final ProviderException e ) {
            LOG.error( "ProviderException requesting version history for " + pageName, e );
        }

        return c;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getCurrentProvider()
     */
    @Override 
    public String getCurrentProvider() {
        return getProvider().getClass().getName();
    }

    /**
     * {@inheritDoc}
     *
     * @see org.apache.wiki.pages.PageManager#getProviderDescription()
     */
    @Override 
    public String getProviderDescription() {
        return m_provider.getProviderInfo();
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getTotalPageCount()
     */
    @Override
    public int getTotalPageCount() {
        try {
            return m_provider.getAllPages().size();
        } catch( final ProviderException e ) {
            LOG.error( "Unable to count pages: ", e );
            return -1;
        }
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getRecentChanges()
     */
    @Override
    public Set< Page > getRecentChanges() {
        try {
            final TreeSet< Page > sortedPages = new TreeSet<>( new PageTimeComparator() );
            sortedPages.addAll( getAllPages() );
            sortedPages.addAll( m_engine.getManager( AttachmentManager.class ).getAllAttachments() );

            return sortedPages;
        } catch( final ProviderException e ) {
            LOG.error( "Unable to fetch all pages: ", e );
            return Collections.emptySet();
        }
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#pageExists(java.lang.String)
     */
    @Override
    public boolean pageExists( final String pageName ) throws ProviderException {
        if (pageName == null || pageName.length() == 0) {
            throw new ProviderException("Illegal page name");
        }

        return m_provider.pageExists(pageName);
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#pageExists(java.lang.String, int)
     */
    @Override
    public boolean pageExists( final String pageName, final int version ) throws ProviderException {
        if( pageName == null || pageName.length() == 0 ) {
            throw new ProviderException( "Illegal page name" );
        }

        if( version == WikiProvider.LATEST_VERSION ) {
            return pageExists( pageName );
        }

        return m_provider.pageExists( pageName, version );
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#wikiPageExists(java.lang.String)
     */
    @Override
    public boolean wikiPageExists( final String page ) {
        if( m_engine.getManager( CommandResolver.class ).getSpecialPageReference( page ) != null ) {
            return true;
        }

        Attachment att = null;
        try {
            if( m_engine.getFinalPageName( page ) != null ) {
                return true;
            }

            att = m_engine.getManager( AttachmentManager.class ).getAttachmentInfo( null, page );
        } catch( final ProviderException e ) {
            LOG.debug( "pageExists() failed to find attachments", e );
        }

        return att != null;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#wikiPageExists(java.lang.String, int)
     */
    @Override
    public boolean wikiPageExists( final String page, final int version ) throws ProviderException {
        if( m_engine.getManager( CommandResolver.class ).getSpecialPageReference( page ) != null ) {
            return true;
        }

        boolean isThere = false;
        final String finalName = m_engine.getFinalPageName( page );
        if( finalName != null ) {
            isThere = pageExists( finalName, version );
        }

        if( !isThere ) {
            //  Go check if such an attachment exists.
            try {
                isThere = m_engine.getManager( AttachmentManager.class ).getAttachmentInfo( null, page, version ) != null;
            } catch( final ProviderException e ) {
                LOG.debug( "wikiPageExists() failed to find attachments", e );
            }
        }

        return isThere;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#deleteVersion(org.apache.wiki.api.core.Page)
     */
    @Override
    public void deleteVersion( final Page page ) throws ProviderException {
        if( page instanceof Attachment ) {
            m_engine.getManager( AttachmentManager.class ).deleteVersion( ( Attachment )page );
        } else {
            m_provider.deleteVersion( page.getName(), page.getVersion() );
            // FIXME: If this was the latest, reindex Lucene, update RefMgr
        }
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#deletePage(java.lang.String)
     */
    @Override
    public void deletePage( final String pageName ) throws ProviderException {
        final Page p = getPage( pageName );
        if( p != null ) {
            if( p instanceof Attachment ) {
                m_engine.getManager( AttachmentManager.class ).deleteAttachment( ( Attachment )p );
            } else {
                final Collection< String > refTo = m_engine.getManager( ReferenceManager.class ).findRefersTo( pageName );
                // May return null, if the page does not exist or has not been indexed yet.

                if( m_engine.getManager( AttachmentManager.class ).hasAttachments( p ) ) {
                    final List< Attachment > attachments = m_engine.getManager( AttachmentManager.class ).listAttachments( p );
                    for( final Attachment attachment : attachments ) {
                        if( refTo != null ) {
                            refTo.remove( attachment.getName() );
                        }

                        m_engine.getManager( AttachmentManager.class ).deleteAttachment( attachment );
                    }
                }
                deletePage( p );
                fireEvent( WikiPageEvent.PAGE_DELETED, pageName );
            }
        }
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#deletePage(org.apache.wiki.api.core.Page)
     */
    @Override
    public void deletePage( final Page page ) throws ProviderException {
        fireEvent( WikiPageEvent.PAGE_DELETE_REQUEST, page.getName() );
        m_provider.deletePage( page.getName() );
        fireEvent( WikiPageEvent.PAGE_DELETED, page.getName() );
    }

    /**
     * This is a simple reaper thread that runs roughly every minute
     * or so (it's not really that important, as long as it runs),
     * and removes all locks that have expired.
     */
    private class LockReaper extends WikiBackgroundThread {
        /**
         * Create a LockReaper for a given engine.
         *
         * @param engine Engine to own this thread.
         */
        public LockReaper( final Engine engine) {
            super( engine, 60 );
            setName( "JSPWiki Lock Reaper" );
        }

        @Override
        public void backgroundTask() {
            final Collection< PageLock > entries = m_pageLocks.values();
            for( final Iterator<PageLock> i = entries.iterator(); i.hasNext(); ) {
                final PageLock p = i.next();

                if ( p.isExpired() ) {
                    i.remove();

                    LOG.debug( "Reaped lock: " + p.getPage() +
                               " by " + p.getLocker() +
                               ", acquired " + p.getAcquisitionTime() +
                               ", and expired " + p.getExpiryTime() );
                }
            }
        }
    }

    // events processing .......................................................

    /**
     * Fires a WikiPageEvent of the provided type and page name
     * to all registered listeners.
     *
     * @param type     the event type to be fired
     * @param pagename the wiki page name as a String
     * @see org.apache.wiki.event.WikiPageEvent
     */
    protected final void fireEvent( final int type, final String pagename ) {
        if( WikiEventManager.isListening( this ) ) {
            WikiEventManager.fireEvent( this, new WikiPageEvent( m_engine, type, pagename ) );
        }
    }

    /**
     * Listens for {@link org.apache.wiki.event.WikiSecurityEvent#PROFILE_NAME_CHANGED}
     * events. If a user profile's name changes, each page ACL is inspected. If an entry contains
     * a name that has changed, it is replaced with the new one. No events are emitted
     * as a consequence of this method, because the page contents are still the same; it is
     * only the representations of the names within the ACL that are changing.
     *
     * @param event The event
     */
    @Override
    public void actionPerformed( final WikiEvent event ) {
        if( !( event instanceof WikiSecurityEvent ) ) {
            return;
        }

        final WikiSecurityEvent se = ( WikiSecurityEvent ) event;
        if( se.getType() == WikiSecurityEvent.PROFILE_NAME_CHANGED ) {
            final UserProfile[] profiles = (UserProfile[]) se.getTarget();
            final Principal[] oldPrincipals = new Principal[] { new WikiPrincipal( profiles[ 0 ].getLoginName() ),
                                                                new WikiPrincipal( profiles[ 0 ].getFullname()),
                                                                new WikiPrincipal( profiles[ 0 ].getWikiName() ) };
            final Principal newPrincipal = new WikiPrincipal( profiles[ 1 ].getFullname() );

            // Examine each page ACL
            try {
                int pagesChanged = 0;
                final Collection< Page > pages = getAllPages();
                for( final Page page : pages ) {
                    final boolean aclChanged = changeAcl( page, oldPrincipals, newPrincipal );
                    if( aclChanged ) {
                        // If the Acl needed changing, change it now
                        try {
                            m_engine.getManager( AclManager.class ).setPermissions( page, page.getAcl() );
                        } catch( final WikiSecurityException e ) {
                            LOG.error("Could not change page ACL for page " + page.getName() + ": " + e.getMessage(), e);
                        }
                        pagesChanged++;
                    }
                }
                LOG.info( "Profile name change for '" + newPrincipal.toString() + "' caused " + pagesChanged + " page ACLs to change also." );
            } catch( final ProviderException e ) {
                // Oooo! This is really bad...
                LOG.error( "Could not change user name in Page ACLs because of Provider error:" + e.getMessage(), e );
            }
        }
    }

    /**
     * For a single wiki page, replaces all Acl entries matching a supplied array of Principals with a new Principal.
     *
     * @param page the wiki page whose Acl is to be modified
     * @param oldPrincipals an array of Principals to replace; all AclEntry objects whose {@link AclEntry#getPrincipal()} method returns
     *                      one of these Principals will be replaced
     * @param newPrincipal the Principal that should receive the old Principals' permissions
     * @return <code>true</code> if the Acl was actually changed; <code>false</code> otherwise
     */
    protected boolean changeAcl( final Page page, final Principal[] oldPrincipals, final Principal newPrincipal ) {
        final Acl acl = page.getAcl();
        boolean pageChanged = false;
        if( acl != null ) {
            final Enumeration< AclEntry > entries = acl.aclEntries();
            final Collection< AclEntry > entriesToAdd = new ArrayList<>();
            final Collection< AclEntry > entriesToRemove = new ArrayList<>();
            while( entries.hasMoreElements() ) {
                final AclEntry entry = entries.nextElement();
                if( ArrayUtils.contains( oldPrincipals, entry.getPrincipal() ) ) {
                    // Create new entry
                    final AclEntry newEntry = Wiki.acls().entry();
                    newEntry.setPrincipal( newPrincipal );
                    final Enumeration< Permission > permissions = entry.permissions();
                    while( permissions.hasMoreElements() ) {
                        final Permission permission = permissions.nextElement();
                        newEntry.addPermission( permission );
                    }
                    pageChanged = true;
                    entriesToRemove.add( entry );
                    entriesToAdd.add( newEntry );
                }
            }
            for( final AclEntry entry : entriesToRemove ) {
                acl.removeEntry( entry );
            }
            for( final AclEntry entry : entriesToAdd ) {
                acl.addEntry( entry );
            }
        }
        return pageChanged;
    }

    /**
     * {@inheritDoc}
     * @see org.apache.wiki.pages.PageManager#getPageSorter()
     */
    @Override
    public PageSorter getPageSorter() {
        return pageSorter;
    }

}
