Add support for IFutureSPFResultListener. See JSPF-94

git-svn-id: https://svn.apache.org/repos/asf/james/jspf/trunk@1202747 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/resolver/src/main/java/org/apache/james/jspf/executor/FutureSPFResult.java b/resolver/src/main/java/org/apache/james/jspf/executor/FutureSPFResult.java
index 687d6be..2733bdf 100644
--- a/resolver/src/main/java/org/apache/james/jspf/executor/FutureSPFResult.java
+++ b/resolver/src/main/java/org/apache/james/jspf/executor/FutureSPFResult.java
@@ -19,6 +19,9 @@
 

 package org.apache.james.jspf.executor;

 

+import java.util.ArrayList;

+import java.util.List;

+

 import org.apache.james.jspf.core.SPFSession;

 

 

@@ -29,6 +32,8 @@
 public class FutureSPFResult extends SPFResult {

     

     private boolean isReady;

+    private List<IFutureSPFResultListener> listeners;

+    private int waiters;

     

     public FutureSPFResult() {

         isReady = false;

@@ -41,9 +46,21 @@
      * 

      */

     public synchronized void setSPFResult(SPFSession session) {

-        setSPFSession(session);

-        isReady = true;

-        notify();

+        if (!isReady) {

+            setSPFSession(session);

+            isReady = true;

+            if (waiters > 0) {

+                notifyAll();

+            }

+            if (listeners != null) {

+                for (IFutureSPFResultListener listener : listeners) {

+                    listener.onSPFResult(this);

+                }

+            }

+            listeners = null;

+        }

+        

+

     }

 

     /**

@@ -53,9 +70,13 @@
     private synchronized void checkReady() {

         while (!isReady) {

             try {

+                waiters++;

                 wait();

             } catch (InterruptedException e) {

-                //

+                // 

+                Thread.interrupted();

+            } finally {

+                waiters--;

             }

         }

     }

@@ -108,4 +129,47 @@
     public synchronized boolean isReady() {

         return isReady;

     }

+

+    /**

+     * Add a {@link IFutureSPFResultListener} which will get notified once {@link #isReady()} returns <code>true</code>

+     * 

+     * @param listener

+     */

+    public synchronized void addListener(IFutureSPFResultListener listener) {

+        if (!isReady) {

+            if (listeners == null) {

+                listeners = new ArrayList<IFutureSPFResultListener>();

+            }

+            listeners.add(listener);

+        } else {

+            listener.onSPFResult(this);

+        }

+    }

+   

+    /**

+     * Remove a {@link IFutureSPFResultListener}

+     * 

+     * @param listener

+     */

+    public synchronized void removeListener(IFutureSPFResultListener listener) {

+        if (listeners != null) {

+            listeners.remove(listener);

+        }

+    }

+    

+    

+    /**

+     * Listener which will get notified once a {@link FutureSPFResult#isReady()} returns <code>true</code>. So it will not block anymore

+     * 

+     *

+     */

+    public interface IFutureSPFResultListener {

+        

+        /**

+         * Get called once a {@link FutureSPFResult} is ready

+         * 

+         * @param result

+         */

+        void onSPFResult(FutureSPFResult result);

+    }

 }