package com4j.util;

import com4j.Com4jObject;
import com4j.ComObjectListener;

import java.util.Map;
import java.util.WeakHashMap;

/**
 * {@link ComObjectListener} implementation that collects all
 * newly created {@link Com4jObject}s
 *
 * <p>
 * The intended use of this class is to record objects created
 * in a certain block and then dispose them all (except a few marked explicitly)
 * at once at some later point.
 *
 * <p>
 * See the following code example for a typical usage:
 * <pre>
 * <pre class=code>
    void foo() {
        // we will start using COM objects.
        // so we'll register the listener and start keeping
        // track of COM objects we create.
        ComObjectCollector col = new ComObjectCollector();
        COM4J.addListener(col);

        try {
            // use COM objects as much as you want
            IFoo foo = doALotOfComStuff();

            // do this to avoid COM objects from disposed by the disposeAll method.
            col.remove(foo);
        } finally {
            // dispose all the COM objects created in this thread
            // since the listener is registered.
            // But "foo" won't be disposed because of the remove method.
            col.disposeAll();

            // make sure to remove the listener
            COM4J.removeListener(col);
        }
    }
 *</pre>
 *
 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
 */
public class ComObjectCollector implements ComObjectListener {
    /**
     * The collected {@link Com4jObject}s
     */
    protected final Map<Com4jObject,Object> objects = new WeakHashMap<Com4jObject,Object>();

    /* (non-Javadoc)
     * @see com4j.ComObjectListener#onNewObject(com4j.Com4jObject)
     */
    public void onNewObject(Com4jObject obj) {
        objects.put(obj,null);
    }

    /**
     * Removes the given object from the list of {@link Com4jObject}s that
     * this class keeps.
     *
     * <p>
     * If the application knows certain {@link Com4jObject} needs to live after
     * the {@link #disposeAll()} method, this method can be called to avoid the object
     * from being disposed.
     *
     * <p>
     * If the object passed in is not known to this {@link ComObjectCollector},
     * it is a no-op.
     * @param obj The object to remove
     */
    public void remove(Com4jObject obj) {
        objects.remove(obj);
    }

    /**
     * Calls the {@link Com4jObject#dispose()} method for all the {@link Com4jObject}s
     * known to this {@link ComObjectCollector}.
     *
     * <p>
     * Each time this method is called, it forgets all the disposed objects.
     */
    public void disposeAll() {
        for( Com4jObject o : objects.keySet() )
            o.dispose();
        objects.clear();
    }
}

@@ -25,59 +25,65 @@
 ort 
-com4j.Com4jObject;%0Aimport com4j.ComObjectListener;%0A
+java.lang.ref.WeakReference;%0Aimport java.util.LinkedList;
 %0Aimp
@@ -96,19 +96,20 @@
 va.util.
-Map
+List
 ;%0Aimport
@@ -119,27 +119,87 @@
 va.util.
-WeakHashMap
+ListIterator;%0A%0Aimport com4j.Com4jObject;%0Aimport com4j.ComObjectListener
 ;%0A%0A/**%0A 
@@ -1455,16 +1455,69 @@
 ke.org)%0A
+ * @author Michael Poindexter (staticsnow@gmail.com)%0A
  */%0Apubl
@@ -1575,16 +1575,18 @@
 tener %7B%0A
+%09%0A
     /**%0A
@@ -1655,19 +1655,34 @@
 d final 
-Map
+List%3CWeakReference
 %3CCom4jOb
@@ -1685,23 +1685,17 @@
 4jObject
-,Object
+%3E
 %3E object
@@ -1706,19 +1706,32 @@
 new 
-WeakHashMap
+LinkedList%3CWeakReference
 %3CCom
@@ -1742,20 +1742,18 @@
 ject
-,Object
+%3E
 %3E();%0A
+    
 %0A   
@@ -1912,20 +1912,47 @@
 cts.
-put(obj,null
+add(new WeakReference%3CCom4jObject%3E(obj)
 );%0A 
@@ -2495,32 +2495,292 @@
     
-    objects.remove(obj);
+%09ListIterator%3CWeakReference%3CCom4jObject%3E%3E itr = objects.listIterator();%0A    %09while(itr.hasNext()) %7B%0A    %09%09Com4jObject o = itr.next().get();%0A    %09%09if(o == obj) %7B //Intentional identity compare...each Wrapper instance owns a single ref.%0A    %09%09%09itr.remove();%0A    %09%09%09break;%0A    %09%09%7D%0A    %09%7D
 %0A   
@@ -3074,16 +3074,30 @@
    for( 
+WeakReference%3C
 Com4jObj
@@ -3099,18 +3099,21 @@
 4jObject
- o
+%3E ref
  : objec
@@ -3118,32 +3118,83 @@
 ects
-.keySet() )%0A      
+) %7B%0A        %09Com4jObject o = ref.get();%0A        %09if(o != null) %7B%0A
       
+  %09%09
 o.di
@@ -3198,24 +3198,45 @@
 .dispose();%0A
+        %09%7D%0A        %7D%0A
         obje

Clean up duplicate refs in ComObjectCollector