/****************************************************************
 * 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.james.mailbox.store;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.james.mailbox.MailboxException;
import org.apache.james.mailbox.MailboxListener;
import org.apache.james.mailbox.MailboxListenerSupport;
import org.apache.james.mailbox.MailboxPath;
import org.apache.james.mailbox.MailboxSession;

public abstract class AbstractDelegatingMailboxListener implements MailboxListener, MailboxListenerSupport{

    private boolean isClosed;
    
    protected AbstractDelegatingMailboxListener() {
    	isClosed = false;
    }
    
    /**
     * Receive the event and dispatch it to the right {@link MailboxListener} depending on {@link Event#getMailboxPath()}
     */
    public void event(Event event) {
        MailboxPath path = event.getMailboxPath();
        Map<MailboxPath, List<MailboxListener>> listeners = getListeners();
        synchronized (listeners) {
            List<MailboxListener> mListeners = listeners.get(path);
            if (mListeners != null && mListeners.isEmpty() == false) {
                
                int sz = mListeners.size();
                for (int i = 0; i < sz; i++) {
                    MailboxListener l = mListeners.get(i);
                    l.event(event);
                    
                }
                
                if (event instanceof MailboxDeletion) {
                    // remove listeners if the mailbox was deleted
                    listeners.remove(path);
                } else if (event instanceof MailboxRenamed) {
                    // handle rename events
                    MailboxRenamed renamed = (MailboxRenamed) event;
                    List<MailboxListener> l = listeners.remove(path);
                    if (l != null) {
                        listeners.put(renamed.getNewPath(), l);
                    }
                }
                
            }  
            
        }
        
        
        List<MailboxListener> globalListeners = getGlobalListeners();
        if (globalListeners != null) {
            synchronized (globalListeners) {
                if (globalListeners.isEmpty() == false) {
                    List<MailboxListener> closedListener = new ArrayList<MailboxListener>();
                    
                    int sz = globalListeners.size();
                    for (int i = 0; i < sz; i++) {
                        MailboxListener l = globalListeners.get(i);
                        l.event(event);
                        
                    }
                    
                  
                    if (closedListener.isEmpty() == false) {
                        globalListeners.removeAll(closedListener);
                    }
                }
            }
        }
        
    }

    /**
     * Close the listener
     */
    public synchronized void close() {
        isClosed = true;
    }
    
    /**
     * Check if closed
     */
    public boolean isClosed() {
        return isClosed;
    }

    /*
     * (non-Javadoc)
     * @see org.apache.james.mailbox.MailboxListenerSupport#addListener(org.apache.james.mailbox.MailboxPath, org.apache.james.mailbox.MailboxListener, org.apache.james.mailbox.MailboxSession)
     */
    public void addListener(MailboxPath path, MailboxListener listener, MailboxSession session) throws MailboxException {
        Map<MailboxPath, List<MailboxListener>> listeners = getListeners();
        synchronized (listeners) {
            List<MailboxListener> mListeners = listeners.get(path);
            if (mListeners == null) {
                mListeners = new ArrayList<MailboxListener>();
                listeners.put(path, mListeners);
            }
            if (mListeners.contains(listener) == false) {
                mListeners.add(listener);
            }        
        }
    }


    /*
     * (non-Javadoc)
     * @see org.apache.james.mailbox.MailboxListenerSupport#addGlobalListener(org.apache.james.mailbox.MailboxListener, org.apache.james.mailbox.MailboxSession)
     */
    public void addGlobalListener(MailboxListener listener, MailboxSession session) throws MailboxException {
        List<MailboxListener> gListeners = getGlobalListeners();
        synchronized (gListeners) {
            gListeners.add(listener);
        }
    }

    
    
    /*
     * (non-Javadoc)
     * @see org.apache.james.mailbox.MailboxListenerSupport#removeListener(org.apache.james.mailbox.MailboxPath, org.apache.james.mailbox.MailboxListener, org.apache.james.mailbox.MailboxSession)
     */
    public void removeListener(MailboxPath mailboxPath, MailboxListener listener, MailboxSession session) throws MailboxException {
        Map<MailboxPath, List<MailboxListener>> listeners = getListeners();
        synchronized (listeners) {
            List<MailboxListener> mListeners = listeners.get(mailboxPath);
            if (mListeners != null) {
                mListeners.remove(listener);
                if (mListeners.isEmpty()) {
                    listeners.remove(mailboxPath);
                }
            }        
        }        
    }

    /*
     * (non-Javadoc)
     * @see org.apache.james.mailbox.MailboxListenerSupport#removeGlobalListener(org.apache.james.mailbox.MailboxListener, org.apache.james.mailbox.MailboxSession)
     */
    public void removeGlobalListener(MailboxListener listener, MailboxSession session) throws MailboxException {
        List<MailboxListener> gListeners = getGlobalListeners();

        synchronized (gListeners) {
            gListeners.remove(listener);
        }
    }

    /**
     * Return the {@link Map} which is used to store the {@link MailboxListener}
     * 
     * @return listeners
     */
    protected abstract Map<MailboxPath, List<MailboxListener>> getListeners();
    
    /**
     * Return the {@link List} which is used tos tore the global {@link MailboxListener}
     * 
     * @return globalListeners
     */
    protected abstract List<MailboxListener> getGlobalListeners();
    
    
}

@@ -6670,16 +6670,54 @@
 ers();%0A%0A
+        if (gListeners != null) %7B%0A    
         
@@ -6736,32 +6736,36 @@
  (gListeners) %7B%0A
+    
             gLis
@@ -6781,32 +6781,46 @@
 move(listener);%0A
+            %7D%0A
         %7D%0A    %7D%0A

Fix possible NPE in some cases.