1 19 20 package org.netbeans.modules.editor.mimelookup.impl; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.beans.PropertyChangeSupport ; 25 import java.lang.ref.WeakReference ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.logging.Logger ; 33 import org.netbeans.api.editor.mimelookup.MimePath; 34 import org.netbeans.spi.editor.mimelookup.Class2LayerFolder; 35 import org.netbeans.spi.editor.mimelookup.InstanceProvider; 36 import org.openide.util.Lookup; 37 import org.openide.util.LookupEvent; 38 import org.openide.util.LookupListener; 39 import org.openide.util.Utilities; 40 import org.openide.util.WeakListeners; 41 42 46 public final class ClassInfoStorage { 47 48 public static final String PROP_CLASS_INFO_CHANGED = "Class2Paths.PROP_CLASS_MAPPING_CHANGED"; public static final String PROP_CLASS_INFO_ADDED = "Class2Paths.PROP_CLASS_MAPPING_ADDED"; public static final String PROP_CLASS_INFO_REMOVED = "Class2Paths.PROP_CLASS_MAPPING_REMOVED"; 52 private static Logger LOG = Logger.getLogger(ClassInfoStorage.class.getName()); 53 54 private static ClassInfoStorage instance = null; 55 56 public static synchronized ClassInfoStorage getInstance() { 57 if (instance == null) { 58 instance = new ClassInfoStorage(); 59 } 60 return instance; 61 } 62 63 private Lookup.Result mappers = null; 64 private L mappersListener = null; 65 66 private final String LOCK = new String ("Class2Paths.LOCK"); private HashMap mapping = new HashMap (); 68 69 private PropertyChangeSupport pcs = new PropertyChangeSupport (this); 70 71 72 private ClassInfoStorage() { 73 mappers = Lookup.getDefault().lookupResult(Class2LayerFolder.class); 74 75 mappersListener = new L(); 76 mappers.addLookupListener((LookupListener) WeakListeners.create(LookupListener.class, mappersListener, mappers)); 77 78 rebuild(); 79 } 80 81 public Info getInfo(String className) { 82 synchronized (LOCK) { 83 if (mapping.containsKey(className)) { 84 return (Info) mapping.get(className); 85 } else { 86 return new Info(this, className, null, null); 87 } 88 } 89 } 90 91 public void addPropertyChangeListener(PropertyChangeListener l) { 92 pcs.addPropertyChangeListener(l); 93 } 94 95 public void removePropertyChangeListener(PropertyChangeListener l) { 96 pcs.removePropertyChangeListener(l); 97 } 98 99 private List rebuild() { 100 synchronized (LOCK) { 101 HashMap newMapping = new HashMap (); 103 Collection newMappers = mappers.allInstances(); 104 105 for (Iterator i = newMappers.iterator(); i.hasNext(); ) { 106 Class2LayerFolder mapper = (Class2LayerFolder) i.next(); 107 108 String className = mapper.getClazz().getName(); 109 String path = mapper.getLayerFolderName(); 110 InstanceProvider ip = mapper.getInstanceProvider(); 111 112 if (path != null) { 113 path = path.trim(); 114 } 115 116 if ((path == null || path.length() == 0) && ip == null) { 117 continue; 119 } 120 121 if (!newMapping.containsKey(className)) { 122 newMapping.put(className, new Info(this, className, path, ip)); 123 } else { 124 LOG.warning("The mapping for class '" + className + "' to folder '" + path + "' and InstanceProvider '" + ip + "' has already been " + "defined by another mapper. Ignoring mapper " + mapper); } 128 } 129 130 HashSet removed = new HashSet (mapping.keySet()); 132 removed.removeAll(newMapping.keySet()); 133 134 HashSet added = new HashSet (newMapping.keySet()); 135 added.removeAll(mapping.keySet()); 136 137 HashSet changed = new HashSet (); 138 for (Iterator i = newMapping.keySet().iterator(); i.hasNext(); ) { 139 String className = (String ) i.next(); 140 141 if (mapping.containsKey(className) && 142 !Utilities.compareObjects(newMapping.get(className), mapping.get(className))) 143 { 144 changed.add(className); 145 } 146 } 147 148 mapping.clear(); 150 mapping.putAll(newMapping); 151 152 ArrayList events = new ArrayList (3); 154 if (!removed.isEmpty()) { 155 events.add(new PropertyChangeEvent (this, PROP_CLASS_INFO_REMOVED, null, removed)); 156 } 157 if (!added.isEmpty()) { 158 events.add(new PropertyChangeEvent (this, PROP_CLASS_INFO_ADDED, null, added)); 159 } 160 if (!changed.isEmpty()) { 161 events.add(new PropertyChangeEvent (this, PROP_CLASS_INFO_CHANGED, null, changed)); 162 } 163 164 return events; 165 } 166 } 167 168 private class L implements LookupListener { 169 170 public void resultChanged(LookupEvent ev) { 171 List events = rebuild(); 173 174 for (Iterator i = events.iterator(); i.hasNext(); ) { 176 PropertyChangeEvent event = (PropertyChangeEvent ) i.next(); 177 pcs.firePropertyChange(event); 178 } 179 } 180 181 } 183 public static final class Info { 184 private ClassInfoStorage storage; 185 private String className; 186 private String extraPath; 187 private String instanceProviderClass; 188 private WeakReference ref; 190 private Info(ClassInfoStorage storage, String className, String extraPath, InstanceProvider instanceProvider) { 191 this.storage = storage; 192 this.className = className; 193 this.extraPath = extraPath == null ? "" : extraPath; if (instanceProvider != null) { 195 this.instanceProviderClass = instanceProvider.getClass().getName(); 196 this.ref = new WeakReference (instanceProvider); 197 } 198 } 199 200 public String getClassName() { 201 return className; 202 } 203 204 public String getExtraPath() { 205 return extraPath; 206 } 207 208 public String getInstanceProviderClass() { 209 return instanceProviderClass; 210 } 211 212 public InstanceProvider getInstanceProvider() { 213 synchronized (storage.LOCK) { 214 if (ref == null) { 216 return null; 217 } 218 219 InstanceProvider ip = (InstanceProvider) ref.get(); 220 if (ip == null) { 221 Collection instances = storage.mappers.allInstances(); 223 for (Iterator i = instances.iterator(); i.hasNext(); ) { 224 Class2LayerFolder mapper = (Class2LayerFolder) i.next(); 225 String className = mapper.getClazz().getName(); 226 227 if (this.className.equals(className)) { 228 ip = mapper.getInstanceProvider(); 229 break; 230 } 231 } 232 233 if (ip != null) { 234 ref = new WeakReference (ip); 235 } 236 } 237 238 return ip; 239 } 240 } 241 242 public boolean equals(Object obj) { 243 if (obj instanceof Info) { 244 Info info = (Info) obj; 245 return this.className.equals(info.className) && 246 Utilities.compareObjects(this.extraPath, info.extraPath) && 247 Utilities.compareObjects(this.instanceProviderClass, info.instanceProviderClass); 248 } else { 249 return false; 250 } 251 } 252 253 public int hashCode() { 254 int hashCode = className.hashCode(); 255 256 if (extraPath != null) { 257 hashCode += 7 * extraPath.hashCode(); 258 } 259 if (instanceProviderClass != null) { 260 hashCode += 13 * instanceProviderClass.hashCode(); 261 } 262 263 return hashCode; 264 } 265 } } 267 | Popular Tags |