#104806: Additional fix, by making the ExcludingLookup result listening using a weak listener pfe_before_pmd pfe_duringpmd_1 pfe_duringpmd_2
authorjtulach@netbeans.org
Fri, 17 Aug 2007 20:13:12 +0000
changeset 290148a9e33bb19
parent 289 896c9677b31e
child 291 6294d05f297b
#104806: Additional fix, by making the ExcludingLookup result listening using a weak listener
openide.util/src/org/openide/util/lookup/ExcludingLookup.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java
     1.1 --- a/openide.util/src/org/openide/util/lookup/ExcludingLookup.java	Wed Aug 15 12:13:23 2007 +0000
     1.2 +++ b/openide.util/src/org/openide/util/lookup/ExcludingLookup.java	Fri Aug 17 20:13:12 2007 +0000
     1.3 @@ -18,10 +18,13 @@
     1.4   */
     1.5  package org.openide.util.lookup;
     1.6  
     1.7 +import java.lang.ref.Reference;
     1.8 +import java.lang.ref.WeakReference;
     1.9  import org.openide.util.Lookup;
    1.10  import org.openide.util.LookupListener;
    1.11  
    1.12  import java.util.*;
    1.13 +import org.openide.util.LookupEvent;
    1.14  
    1.15  
    1.16  /** Allows exclusion of certain instances from lookup.
    1.17 @@ -49,6 +52,7 @@
    1.18          }
    1.19      }
    1.20  
    1.21 +    @Override
    1.22      public String toString() {
    1.23          return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
    1.24      }
    1.25 @@ -80,6 +84,7 @@
    1.26          }
    1.27      }
    1.28  
    1.29 +    @Override
    1.30      public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
    1.31          if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
    1.32              return null;
    1.33 @@ -244,12 +249,14 @@
    1.34       */
    1.35      private final class R<T> extends WaitableResult<T> implements LookupListener {
    1.36          private Result<T> result;
    1.37 +        private WeakResult<T> weak;
    1.38          private Object listeners;
    1.39          private Class<?> from;
    1.40  
    1.41          R(Class<?> from, Result<T> delegate) {
    1.42              this.from = from;
    1.43              this.result = delegate;
    1.44 +            this.weak = new WeakResult<T>(this, delegate);
    1.45          }
    1.46  
    1.47          protected void beforeLookup(Template t) {
    1.48 @@ -267,7 +274,7 @@
    1.49              }
    1.50  
    1.51              if (add) {
    1.52 -                result.addLookupListener(this);
    1.53 +                result.addLookupListener(weak);
    1.54              }
    1.55          }
    1.56  
    1.57 @@ -280,7 +287,7 @@
    1.58              }
    1.59  
    1.60              if (remove) {
    1.61 -                result.removeLookupListener(this);
    1.62 +                result.removeLookupListener(weak);
    1.63              }
    1.64          }
    1.65  
    1.66 @@ -292,10 +299,12 @@
    1.67              return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
    1.68          }
    1.69  
    1.70 +        @Override
    1.71          public Set<Class<? extends T>> allClasses() {
    1.72              return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
    1.73          }
    1.74  
    1.75 +        @Override
    1.76          public Collection<? extends Item<T>> allItems() {
    1.77              return openCol(result.allItems(), 2);
    1.78          }
    1.79 @@ -326,5 +335,67 @@
    1.80              final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
    1.81              AbstractLookup.notifyListeners(ll, newev, evAndListeners);
    1.82          }
    1.83 -    }
    1.84 +    } // end of R
    1.85 +    
    1.86 +    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
    1.87 +        private Lookup.Result source;
    1.88 +        private Reference<R<T>> result;
    1.89 +        
    1.90 +        public WeakResult(R<T> r, Lookup.Result<T> s) {
    1.91 +            this.result = new WeakReference<R<T>>(r);
    1.92 +            this.source = s;
    1.93 +        }
    1.94 +        
    1.95 +        protected void beforeLookup(Lookup.Template t) {
    1.96 +            R r = (R)result.get();
    1.97 +            if (r != null) {
    1.98 +                r.beforeLookup(t);
    1.99 +            } else {
   1.100 +                source.removeLookupListener(this);
   1.101 +            }
   1.102 +        }
   1.103 +
   1.104 +        protected void collectFires(Collection<Object> evAndListeners) {
   1.105 +            R<T> r = result.get();
   1.106 +            if (r != null) {
   1.107 +                r.collectFires(evAndListeners);
   1.108 +            } else {
   1.109 +                source.removeLookupListener(this);
   1.110 +            }
   1.111 +        }
   1.112 +
   1.113 +        public void addLookupListener(LookupListener l) {
   1.114 +            assert false;
   1.115 +        }
   1.116 +
   1.117 +        public void removeLookupListener(LookupListener l) {
   1.118 +            assert false;
   1.119 +        }
   1.120 +
   1.121 +        public Collection<T> allInstances() {
   1.122 +            assert false;
   1.123 +            return null;
   1.124 +        }
   1.125 +
   1.126 +        public void resultChanged(LookupEvent ev) {
   1.127 +            R r = (R)result.get();
   1.128 +            if (r != null) {
   1.129 +                r.resultChanged(ev);
   1.130 +            } else {
   1.131 +                source.removeLookupListener(this);
   1.132 +            }
   1.133 +        }
   1.134 +
   1.135 +        @Override
   1.136 +        public Collection<? extends Item<T>> allItems() {
   1.137 +            assert false;
   1.138 +            return null;
   1.139 +        }
   1.140 +
   1.141 +        @Override
   1.142 +        public Set<Class<? extends T>> allClasses() {
   1.143 +            assert false;
   1.144 +            return null;
   1.145 +        }
   1.146 +    } // end of WeakResult
   1.147  }
     2.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Wed Aug 15 12:13:23 2007 +0000
     2.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Fri Aug 17 20:13:12 2007 +0000
     2.3 @@ -28,6 +28,7 @@
     2.4  import junit.framework.*;
     2.5  import org.netbeans.junit.*;
     2.6  import java.io.Serializable;
     2.7 +import java.lang.ref.Reference;
     2.8  import org.openide.util.Lookup.Template;
     2.9  
    2.10  public class AbstractLookupBaseHid extends NbTestCase {
    2.11 @@ -1567,10 +1568,46 @@
    2.12          Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
    2.13          assertTrue("It is empty: " + c, c.isEmpty());
    2.14      }
    2.15 +
    2.16 +    public void testCanGCResults() throws Exception {
    2.17 +        class L implements LookupListener {
    2.18 +            int cnt;
    2.19 +            
    2.20 +            public void resultChanged(LookupEvent ev) {
    2.21 +                cnt++;
    2.22 +            }
    2.23 +            
    2.24 +        }
    2.25 +        L listener1 = new L();
    2.26 +        L listener2 = new L();
    2.27 +        
    2.28 +        Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
    2.29 +        Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
    2.30 +        
    2.31 +        assertEquals("Empty1", 0, res1.allItems().size());
    2.32 +        assertEquals("Empty2", 0, res2.allItems().size());
    2.33 +        
    2.34 +        res1.addLookupListener(listener1);
    2.35 +        res2.addLookupListener(listener2);
    2.36 +        
    2.37 +        addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
    2.38 +        this.ic.add("Ahoj");
    2.39 +        
    2.40 +        assertEquals("Change1", 1, listener1.cnt);
    2.41 +        assertEquals("Change2", 1, listener2.cnt);
    2.42 +        
    2.43 +        assertEquals("Full1", 1, res1.allItems().size());
    2.44 +        assertEquals("Full2", 1, res2.allItems().size());
    2.45 +        
    2.46 +        
    2.47 +        Reference<Object> ref2 = new WeakReference<Object>(res2);
    2.48 +        res2 = null;
    2.49 +        assertGC("Result can disappear", ref2);
    2.50 +    }
    2.51      
    2.52      /** Adds instances to the instance lookup.
    2.53       */
    2.54 -    private void addInstances (Object[] instances) {
    2.55 +    private void addInstances (Object... instances) {
    2.56          for (int i = 0; i < instances.length; i++) {
    2.57              ic.add(instances[i]);
    2.58          }