1 19 package org.netbeans.modules.j2ee.metadata; 20 21 import org.netbeans.spi.java.classpath.ClassPathImplementation; 22 23 import java.util.List ; 24 import java.util.ArrayList ; 25 import java.util.Iterator ; 26 import java.util.Collections ; 27 import java.beans.PropertyChangeListener ; 28 import java.beans.PropertyChangeEvent ; 29 import java.lang.ref.WeakReference ; 30 import java.util.concurrent.CopyOnWriteArraySet ; 31 import org.netbeans.spi.java.classpath.PathResourceImplementation; 32 import org.openide.util.Utilities; 33 import org.openide.util.WeakListeners; 34 35 40 public class WeakProxyClassPathImplementation implements ClassPathImplementation { 41 42 final private CopyOnWriteArraySet <WeakReference <ClassPathImplementation>> classPathRefs = new CopyOnWriteArraySet <WeakReference <ClassPathImplementation>>(); 43 final private PropertyChangeListener classPathsListener = new DelegatesListener (); 44 45 private List <PathResourceImplementation> resourcesCache; 46 private ArrayList <PropertyChangeListener > listeners; 47 48 public WeakProxyClassPathImplementation (ClassPathImplementation[] classPaths) { 49 if (classPaths == null) { 50 throw new IllegalArgumentException (); 51 } 52 for (ClassPathImplementation classPath : classPaths) { 53 if (classPaths == null) { 54 continue; 55 } 56 classPath.addPropertyChangeListener (WeakListeners.propertyChange(classPathsListener, classPath)); 57 classPathRefs.add(new CleanupReference<ClassPathImplementation>(classPath)); 58 } 59 } 60 61 public List <PathResourceImplementation> getResources() { 62 synchronized (this) { 63 if (this.resourcesCache != null) { 64 return this.resourcesCache; 65 } 66 } 67 List <PathResourceImplementation> result = new ArrayList <PathResourceImplementation>(classPathRefs.size() * 10); 68 for (WeakReference <ClassPathImplementation> classPathRef : classPathRefs) { 69 ClassPathImplementation classPath = classPathRef.get(); 70 if (classPath == null) { 71 continue; 72 } 73 List <? extends PathResourceImplementation> subPath = classPath.getResources(); 74 assert subPath != null : "ClassPathImplementation.getResources() returned null. ClassPathImplementation.class: " 75 + classPath.getClass().toString() + " ClassPathImplementation: " + classPath.toString(); 76 result.addAll(subPath); 77 } 78 synchronized (this) { 79 if (this.resourcesCache == null) { 80 resourcesCache = Collections.unmodifiableList(result); 81 } 82 return this.resourcesCache; 83 } 84 } 85 86 public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { 87 if (this.listeners == null) 88 this.listeners = new ArrayList <PropertyChangeListener >(); 89 this.listeners.add (listener); 90 } 91 92 public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { 93 if (this.listeners == null) 94 return; 95 this.listeners.remove (listener); 96 } 97 98 public String toString () { 99 StringBuffer builder = new StringBuffer ("["); for (WeakReference <ClassPathImplementation> classPathRef : classPathRefs) { 101 ClassPathImplementation classPath = classPathRef.get(); 102 if (classPath != null) { 103 builder.append (classPath.toString()); 104 builder.append(", "); } 106 } 107 builder.append ("]"); return builder.toString (); 109 } 110 111 private void change(String propertyName) { 112 Iterator it = null; 113 synchronized (this) { 114 WeakProxyClassPathImplementation.this.resourcesCache = null; if (WeakProxyClassPathImplementation.this.listeners == null) { 116 return; 117 } 118 it = ((ArrayList )WeakProxyClassPathImplementation.this.listeners.clone()).iterator(); 119 } 120 PropertyChangeEvent event = new PropertyChangeEvent (this, propertyName, null, null); 121 while (it.hasNext()) { 122 ((PropertyChangeListener )it.next()).propertyChange (event); 123 } 124 } 125 126 private class DelegatesListener implements PropertyChangeListener { 127 128 public void propertyChange(PropertyChangeEvent evt) { 129 change(evt.getPropertyName()); 130 } 131 } 132 133 private class CleanupReference<T> extends WeakReference <T> implements Runnable { 134 135 public CleanupReference(T referent) { 136 super(referent, Utilities.activeReferenceQueue()); 137 } 138 139 public void run() { 140 classPathRefs.remove(this); 141 change(ClassPathImplementation.PROP_RESOURCES); 142 } 143 } 144 145 } 146 | Popular Tags |