KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > mimelookup > impl > ClassInfoStorage


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor.mimelookup.impl;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.beans.PropertyChangeSupport JavaDoc;
25 import java.lang.ref.WeakReference JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.logging.Logger JavaDoc;
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 /**
43  *
44  * @author vita
45  */

46 public final class ClassInfoStorage {
47     
48     public static final String JavaDoc PROP_CLASS_INFO_CHANGED = "Class2Paths.PROP_CLASS_MAPPING_CHANGED"; //NOI18N
49
public static final String JavaDoc PROP_CLASS_INFO_ADDED = "Class2Paths.PROP_CLASS_MAPPING_ADDED"; //NOI18N
50
public static final String JavaDoc PROP_CLASS_INFO_REMOVED = "Class2Paths.PROP_CLASS_MAPPING_REMOVED"; //NOI18N
51

52     private static Logger JavaDoc 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 JavaDoc LOCK = new String JavaDoc("Class2Paths.LOCK"); //NOI18N
67
private HashMap JavaDoc mapping = new HashMap JavaDoc();
68     
69     private PropertyChangeSupport JavaDoc pcs = new PropertyChangeSupport JavaDoc(this);
70     
71     /** Creates a new instance of Class2Paths */
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 JavaDoc 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 JavaDoc l) {
92         pcs.addPropertyChangeListener(l);
93     }
94     
95     public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
96         pcs.removePropertyChangeListener(l);
97     }
98
99     private List JavaDoc rebuild() {
100         synchronized (LOCK) {
101             // Gather the new mapping information
102
HashMap JavaDoc newMapping = new HashMap JavaDoc();
103             Collection JavaDoc newMappers = mappers.allInstances();
104             
105             for (Iterator JavaDoc i = newMappers.iterator(); i.hasNext(); ) {
106                 Class2LayerFolder mapper = (Class2LayerFolder) i.next();
107                 
108                 String JavaDoc className = mapper.getClazz().getName();
109                 String JavaDoc 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                     // Hmm, why anybody registered mapper, which doesn't provide any info.
118
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 '" + //NOI18N
125
path + "' and InstanceProvider '" + ip + "' has already been " + //NOI18N
126
"defined by another mapper. Ignoring mapper " + mapper); //NOI18N
127
}
128             }
129         
130             // Compute differences
131
HashSet JavaDoc removed = new HashSet JavaDoc(mapping.keySet());
132             removed.removeAll(newMapping.keySet());
133             
134             HashSet JavaDoc added = new HashSet JavaDoc(newMapping.keySet());
135             added.removeAll(mapping.keySet());
136             
137             HashSet JavaDoc changed = new HashSet JavaDoc();
138             for (Iterator JavaDoc i = newMapping.keySet().iterator(); i.hasNext(); ) {
139                 String JavaDoc className = (String JavaDoc) 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             // Update the mapping
149
mapping.clear();
150             mapping.putAll(newMapping);
151             
152             // Generate events
153
ArrayList JavaDoc events = new ArrayList JavaDoc(3);
154             if (!removed.isEmpty()) {
155                 events.add(new PropertyChangeEvent JavaDoc(this, PROP_CLASS_INFO_REMOVED, null, removed));
156             }
157             if (!added.isEmpty()) {
158                 events.add(new PropertyChangeEvent JavaDoc(this, PROP_CLASS_INFO_ADDED, null, added));
159             }
160             if (!changed.isEmpty()) {
161                 events.add(new PropertyChangeEvent JavaDoc(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             // Update mapping information
172
List JavaDoc events = rebuild();
173             
174             // Fire change events if neccessary
175
for (Iterator JavaDoc i = events.iterator(); i.hasNext(); ) {
176                 PropertyChangeEvent JavaDoc event = (PropertyChangeEvent JavaDoc) i.next();
177                 pcs.firePropertyChange(event);
178             }
179         }
180         
181     } // End of L class
182

183     public static final class Info {
184         private ClassInfoStorage storage;
185         private String JavaDoc className;
186         private String JavaDoc extraPath;
187         private String JavaDoc instanceProviderClass;
188         private WeakReference JavaDoc ref; // TODO: This should really be a timed-weak-ref
189

190         private Info(ClassInfoStorage storage, String JavaDoc className, String JavaDoc extraPath, InstanceProvider instanceProvider) {
191             this.storage = storage;
192             this.className = className;
193             this.extraPath = extraPath == null ? "" : extraPath; //NOI18N
194
if (instanceProvider != null) {
195                 this.instanceProviderClass = instanceProvider.getClass().getName();
196                 this.ref = new WeakReference JavaDoc(instanceProvider);
197             }
198         }
199         
200         public String JavaDoc getClassName() {
201             return className;
202         }
203         
204         public String JavaDoc getExtraPath() {
205             return extraPath;
206         }
207         
208         public String JavaDoc getInstanceProviderClass() {
209             return instanceProviderClass;
210         }
211         
212         public InstanceProvider getInstanceProvider() {
213             synchronized (storage.LOCK) {
214                 // There was no instance provider specified
215
if (ref == null) {
216                     return null;
217                 }
218                 
219                 InstanceProvider ip = (InstanceProvider) ref.get();
220                 if (ip == null) {
221                     // Instance provider has been GCed, recreate it
222
Collection JavaDoc instances = storage.mappers.allInstances();
223                     for (Iterator JavaDoc i = instances.iterator(); i.hasNext(); ) {
224                         Class2LayerFolder mapper = (Class2LayerFolder) i.next();
225                         String JavaDoc 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 JavaDoc(ip);
235                     }
236                 }
237                 
238                 return ip;
239             }
240         }
241
242         public boolean equals(Object JavaDoc 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     } // End of Info class
266
}
267
Popular Tags