package ie.omk.smpp.event;

import ie.omk.smpp.Session;
import ie.omk.smpp.message.SMPPPacket;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of the {@link EventDispatcher} that uses Java's
 * {@link Executor} framework to dispatch events. If no other executor
 * is supplied, then a {@link ThreadPoolExecutor} will be created
 * at {@link #init} time.
 */
public class TaskExecutorEventDispatcher extends AbstractEventDispatcher {
    private static final Logger LOG =
        LoggerFactory.getLogger(TaskExecutorEventDispatcher.class);

    private Executor executor;
    private int threadCount = 3;
    
    public void destroy() {
        if (executor instanceof ExecutorService) {
            ((ExecutorService) executor).shutdownNow();
        }
    }

    public void init() {
        if (executor == null) {
            executor = Executors.newFixedThreadPool(threadCount);
        }
    }

    public void notifyObservers(final Session conn, final SMPPEvent event) {
        final SessionObserver[] observers = getObserverList();
        executor.execute(new Runnable() {
            public void run() {
                doUpdate(observers, conn, event);
            }
        });
    }

    public void notifyObservers(final Session conn, final SMPPPacket packet) {
        final SessionObserver[] observers = getObserverList();
        executor.execute(new Runnable() {
            public void run() {
                doPacketReceived(observers, conn, packet);
            }
        });
    }

    /**
     * Set the number of threads to create in a <tt>ThreadPoolExecutor</tt>
     * for event dispatching. This property is ignored if an
     * <tt>executor</tt> is directly set on this object.
     * @param threadCount The number of threads to create in the thread pool.
     */
    public void setThreadCount(int threadCount) {
        this.threadCount = threadCount;
    }

    public Executor getExecutor() {
        return executor;
    }

    public void setExecutor(Executor executor) {
        this.executor = executor;
    }
    
    private void doUpdate(SessionObserver[] observers, Session session, SMPPEvent event) {
        for (SessionObserver observer : observers) {
            try {
                observer.update(session, event);
            } catch (Throwable t) {
                LOG.error("Observer " + observer + " threw an exception", t);
            }
        }
    }
    
    private void doPacketReceived(
            SessionObserver[] observers, Session session, SMPPPacket packet) {
        for (SessionObserver observer : observers) {
            try {
                observer.packetReceived(session, packet);
            } catch (Throwable t) {
                LOG.error("Observer " + observer + " threw an exception", t);
            }
        }
    }
}

@@ -87,16 +87,93 @@
 PPacket;
+%0Aimport ie.omk.smpp.util.APIConfig;%0Aimport ie.omk.smpp.util.APIConfigFactory;
 %0A%0Aimport
@@ -628,16 +628,455 @@
 %7D time.%0A
+ * %3Cp%3E%0A * The number of threads created in the %3Ctt%3EThreadPoolExecutor%3C/tt%3E%0A * is determined from the %7B@link #setThreadCount(int) threadCount%7D%0A * property, which by default is set to %3Ctt%3E0%3C/tt%3E. If the application%0A * does not override this value, then the %7B@link APIConfig%7D will%0A * be consulted for the %7B@link APIConfig#EVENT_THREAD_POOL_SIZE%7D property. If%0A * no value is set there, then a default value of %3Ctt%3E3%3C/tt%3E will be used.%0A * %3C/p%3E%0A
  */%0Apubl
@@ -1314,17 +1314,17 @@
 Count = 
-3
+0
 ;%0A    %0A 
@@ -1527,24 +1527,170 @@
  == null) %7B%0A
+            int numThreads = threadCount;%0A            if (numThreads %3C 1) %7B%0A                numThreads = getNumThreadsFromConfig();%0A            %7D%0A
             
@@ -1729,27 +1729,26 @@
 eadPool(
-t
+numT
 hread
-Count
+s
 );%0A     
@@ -3658,10 +3658,189 @@
 %7D%0A    %7D%0A
+    %0A    private int getNumThreadsFromConfig() %7B%0A        APIConfig config = APIConfigFactory.getConfig();%0A        return config.getInt(APIConfig.EVENT_THREAD_POOL_SIZE, 3);%0A    %7D%0A
 %7D%0A

Read the thread pool size from the API config.