2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.settings.convertors;
46
import org.openide.modules.ModuleInfo;
47
import org.openide.util.Lookup;
48
import org.openide.util.LookupListener;
49
import org.openide.util.LookupEvent;
51
/** Manager providing ModuleInfo of all modules presented in the system.
52
* @author Jan Pokorsky
54
final class ModuleInfoManager {
55
private final static ModuleInfoManager mim = new ModuleInfoManager();;
57
/** all modules <code bas name, ModuleInfo> */
58
private HashMap<String, ModuleInfo> modules = null;
59
/** lookup query to find out all modules */
60
private Lookup.Result<ModuleInfo> modulesResult = null;
61
/** <ModuleInfo, PCL> */
62
private HashMap<ModuleInfo, PCL> mapOfListeners;
63
/** Creates a new instance of ModuleInfoManager */
64
private ModuleInfoManager() {
67
public final static ModuleInfoManager getDefault() {
72
* @param codeBaseName module code base name (without revision)
73
* @return module info or null
75
public ModuleInfo getModule(String codeBaseName) {
76
Collection<? extends ModuleInfo> l = null;
77
if (modules == null) {
78
l = getModulesResult().allInstances();
81
if (modules == null) fillModules(l);
82
return (ModuleInfo) modules.get(codeBaseName);
86
private Lookup.Result<ModuleInfo> getModulesResult() {
88
if (modulesResult == null) {
89
Lookup lookup = org.netbeans.core.NbTopManager.getModuleLookup();
90
modulesResult = lookup.
91
lookup(new Lookup.Template<ModuleInfo>(ModuleInfo.class));
92
modulesResult.addLookupListener(new LookupListener() {
93
public void resultChanged(LookupEvent ev) {
94
Collection<? extends ModuleInfo> l = getModulesResult().allInstances();
95
XMLSettingsSupport.err.fine("Modules changed: " + l); // NOI18N
99
reloaded = replaceReloadedModules();
100
XMLSettingsSupport.err.fine("Reloaded modules: " + reloaded); // NOI18N
102
notifyReloads(reloaded);
106
return modulesResult;
110
/** notify registered listeners about reloaded modules
111
* @param l a list of PCLs of reloaded modules
113
private void notifyReloads(List l) {
114
Iterator it = l.iterator();
115
while (it.hasNext()) {
116
PCL lsnr = (PCL) it.next();
121
/** recompute accessible modules.
122
* @param l a collection of module infos
124
private void fillModules(Collection<? extends ModuleInfo> l) {
125
HashMap<String, ModuleInfo> m = new HashMap<String, ModuleInfo>((l.size() << 2) / 3 + 1);
126
for (ModuleInfo mi: l) {
127
m.put(mi.getCodeNameBase(), mi);
132
/** replace old MIs of reloaded modules with new ones
133
* @return the list of PCLs of reloaded modules
135
private List<PCL> replaceReloadedModules() {
136
if (mapOfListeners == null) return Collections.emptyList();
138
Iterator<ModuleInfo> it = new ArrayList<ModuleInfo>(mapOfListeners.keySet()).iterator();
139
List<PCL> reloaded = new ArrayList<PCL>();
141
while (it.hasNext()) {
142
ModuleInfo mi = it.next();
143
ModuleInfo miNew = modules.get(mi.getCodeNameBase());
144
if (mi != miNew && miNew != null) {
145
PCL lsnr = mapOfListeners.remove(mi);
146
lsnr.setModuleInfo(miNew);
148
mapOfListeners.put(miNew, lsnr);
155
/** look up ModuleInfo according to clazz
156
* @param clazz class used in the look up query
157
* @return module info of the module which clazz was loaded from
159
public ModuleInfo getModuleInfo(Class clazz) {
160
Iterator it = getModulesResult().allInstances().iterator();
161
while (it.hasNext()) {
162
ModuleInfo mi = (ModuleInfo) it.next();
163
if (mi.owns(clazz)) return mi;
168
/** register listener to be notified about changes of mi
169
* @param sdc convertor
170
* @param mi ModuleInfo for which the listener will be registered
172
public synchronized void registerPropertyChangeListener(SerialDataConvertor sdc, ModuleInfo mi) {
173
if (mapOfListeners == null) {
174
mapOfListeners = new HashMap<ModuleInfo,PCL>(modules.size());
177
PCL lsnr = mapOfListeners.get(mi);
180
mapOfListeners.put(mi, lsnr);
182
PropertyChangeListener pcl = org.openide.util.WeakListeners.propertyChange(sdc, lsnr);
183
lsnr.addPropertyChangeListener(sdc, pcl);
186
/** unregister listener
187
* @param sdc convertor
188
* @param mi ModuleInfo
189
* @see #registerPropertyChangeListener
191
public synchronized void unregisterPropertyChangeListener(SerialDataConvertor sdc, ModuleInfo mi) {
192
if (mapOfListeners == null) return;
193
PCL lsnr = (PCL) mapOfListeners.get(mi);
195
lsnr.removePropertyChangeListener(sdc);
196
// do not try to discard lsnr to allow to track reloading of a module
200
/** find out if a module was reloaded (disable+enabled)
201
* @param mi ModuleInfo of the queried module
202
* @return reload status
204
public synchronized boolean isReloaded(ModuleInfo mi) {
205
if (mapOfListeners == null) return false;
206
PCL lsnr = (PCL) mapOfListeners.get(mi);
207
return lsnr != null && lsnr.isReloaded();
210
/** find out if a module was reloaded (disable+enabled)
211
* @param codeBaseName ModuleInfo's code base name of the queried module
212
* @return reload status
214
public synchronized boolean isReloaded(String codeBaseName) {
215
if (mapOfListeners == null) return false;
216
return isReloaded(getModule(codeBaseName));
219
/** ModuleInfo status provider shared by registered listeners
220
* @see #registerPropertyChangeListener
222
private static final class PCL implements PropertyChangeListener {
223
/** a flag to be set to true when a module has been disabled */
224
private boolean aModuleHasBeenChanged = false;
225
private boolean wasModuleEnabled;
226
private ModuleInfo mi;
227
private PropertyChangeSupport changeSupport;
228
/** map of registered listeners <SerialDataConvertor, PropertyChangeListener> */
229
private Map<SerialDataConvertor, PropertyChangeListener> origs;
231
public PCL(ModuleInfo mi) {
233
wasModuleEnabled = mi.isEnabled();
234
mi.addPropertyChangeListener(this);
237
/** replace an old module info with a new one */
238
void setModuleInfo(ModuleInfo mi) {
239
this.mi.removePropertyChangeListener(this);
240
aModuleHasBeenChanged = true;
242
mi.addPropertyChangeListener(this);
245
/** notify listeners about a module reload */
246
void notifyReload() {
247
firePropertyChange();
250
boolean isReloaded() {
251
return aModuleHasBeenChanged;
254
public void propertyChange(java.beans.PropertyChangeEvent evt) {
255
if(ModuleInfo.PROP_ENABLED.equals(evt.getPropertyName())) {
259
if (!Boolean.TRUE.equals (evt.getNewValue ())) {
260
// a module has been disabled, use full checks
261
aModuleHasBeenChanged = true;
263
// if wasModuleEnabled was true, we changed state
264
change = wasModuleEnabled;
266
// a module was enabled, if wasModuleEnabled was false
268
change = !wasModuleEnabled;
271
// update wasModuleEnabled to current state of the module
272
wasModuleEnabled = mi.isEnabled();
275
//instanceCookieChanged(null);
276
firePropertyChange();
281
/** adds listener per convertor */
282
public void addPropertyChangeListener(SerialDataConvertor sdc, PropertyChangeListener listener) {
283
synchronized (this) {
284
if (changeSupport == null) {
285
changeSupport = new PropertyChangeSupport(this);
286
origs = new WeakHashMap<SerialDataConvertor, PropertyChangeListener>();
289
PropertyChangeListener old = (PropertyChangeListener) origs.get(sdc);
290
if (old != null) return;
291
origs.put(sdc, listener);
293
changeSupport.addPropertyChangeListener(listener);
296
public void removePropertyChangeListener(PropertyChangeListener listener) {
297
if (changeSupport != null) {
298
changeSupport.removePropertyChangeListener(listener);
302
/** unregister listener registered per convertor */
303
public void removePropertyChangeListener(SerialDataConvertor sdc) {
304
synchronized (this) {
305
if (origs == null) return;
307
PropertyChangeListener pcl = (PropertyChangeListener) origs.remove(sdc);
309
removePropertyChangeListener(pcl);
314
private void firePropertyChange() {
315
if (changeSupport != null) {
316
changeSupport.firePropertyChange(ModuleInfo.PROP_ENABLED, null, null);