/**
* Licensed to niosmtp developers ('niosmtp') under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* niosmtp 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 me.normanmaurer.niosmtp.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import me.normanmaurer.niosmtp.SMTPClientFuture;
import me.normanmaurer.niosmtp.SMTPClientFutureListener;
import me.normanmaurer.niosmtp.transport.SMTPClientSession;

/**
 * 
 * Abstract base class for {@link SMTPClientFuture} implementations 
 * 
 * @author Norman Maurer
 *
 * @param <E>
 */
public abstract class AbstractSMTPClientFuture<E> implements SMTPClientFuture<E>{

    private List<SMTPClientFutureListener<E>> listeners;
    private volatile SMTPClientSession session;

    /**
     * Notify all registered {@link SMTPClientFutureListener}'s
     */
    protected final void notifyListeners() {
    	Iterator<SMTPClientFutureListener<E>> it = null;
        synchronized (this) {
            if (listeners != null) {
                // notify the listeners
                it  = listeners.iterator();

                listeners = null;
            }
        }
        if (it != null) {
            while(it.hasNext()) {
                it.next().operationComplete(this);
            }
        }
    }

    @Override
    public final synchronized void addListener(SMTPClientFutureListener<E> listener) {

        if (isDone()) {
            listener.operationComplete(this);
        } else {
            if (listeners == null) {
                listeners = new ArrayList<SMTPClientFutureListener<E>>();
            }
            listeners.add(listener);

        }
    }

    @Override
    public final synchronized void removeListener(SMTPClientFutureListener<E> listener) {
        if (!isDone()) {
            if (listeners != null) {
                listeners.remove(listener);
            }
            
        }
    }
    

    @Override
    public final SMTPClientSession getSession() {
        return session;
    }

    /**
     * Set the {@link SMTPClientSession} which does belong to this {@link SMTPClientFuture}
     * 
     * @param session
     */
    public final void setSMTPClientSession(SMTPClientSession session) {
        this.session = session;
    }

}

@@ -887,16 +887,74 @@
 .List;%0A%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 import m
@@ -994,16 +994,16 @@
 Future;%0A
-
 import m
@@ -1427,17 +1427,119 @@
 ession;%0A
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSMTPClientFuture.class);%0A    
 %0A
-
     /**%0A
@@ -1999,42 +1999,361 @@
     
-it.next().operationComplete(this);
+SMTPClientFutureListener%3CE%3E listener = null;%0A                try %7B%0A                    listener = it.next();%0A                    listener.operationComplete(this);%0A                %7D catch (Throwable e) %7B%0A                    LOGGER.warn(%22Exception thrown while executing %22 + SMTPClientFutureListener.class.getName() + %22 %22 + listener, e);%0A                %7D
 %0A   

Make sure all SMTPClientFutureListeners get notified even on an unchecked Exception. See #20