Lines 41-64
Link Here
|
41 |
|
41 |
|
42 |
package org.netbeans.api.project.libraries; |
42 |
package org.netbeans.api.project.libraries; |
43 |
|
43 |
|
44 |
|
|
|
45 |
import org.netbeans.api.project.libraries.Library; |
46 |
import org.netbeans.spi.project.libraries.LibraryImplementation; |
47 |
import org.netbeans.spi.project.libraries.LibraryProvider; |
48 |
import org.openide.util.Lookup; |
49 |
import org.openide.util.LookupListener; |
50 |
import org.openide.util.LookupEvent; |
51 |
|
52 |
import java.beans.PropertyChangeSupport; |
44 |
import java.beans.PropertyChangeSupport; |
53 |
import java.beans.PropertyChangeListener; |
45 |
import java.beans.PropertyChangeListener; |
54 |
import java.beans.PropertyChangeEvent; |
46 |
import java.beans.PropertyChangeEvent; |
55 |
import java.io.IOException; |
47 |
import java.io.IOException; |
56 |
import java.util.*; |
48 |
import java.net.URL; |
|
|
49 |
import java.util.ArrayList; |
50 |
import java.util.Collection; |
51 |
import java.util.HashSet; |
52 |
import java.util.List; |
53 |
import java.util.Map; |
54 |
import java.util.Set; |
55 |
import org.netbeans.modules.project.libraries.LibraryAccessor; |
57 |
import org.netbeans.modules.project.libraries.WritableLibraryProvider; |
56 |
import org.netbeans.modules.project.libraries.WritableLibraryProvider; |
58 |
import org.netbeans.spi.project.libraries.LibraryFactory; |
57 |
import org.netbeans.modules.project.libraries.ui.LibrariesModel; |
|
|
58 |
import org.netbeans.spi.project.libraries.ArealLibraryProvider; |
59 |
import org.netbeans.spi.project.libraries.LibraryImplementation; |
60 |
import org.netbeans.spi.project.libraries.LibraryProvider; |
61 |
import org.netbeans.spi.project.libraries.LibraryStorageArea; |
62 |
import org.netbeans.spi.project.libraries.LibraryTypeProvider; |
59 |
import org.netbeans.spi.project.libraries.support.LibrariesSupport; |
63 |
import org.netbeans.spi.project.libraries.support.LibrariesSupport; |
60 |
|
64 |
import org.openide.util.Lookup; |
61 |
// XXX make getLibraries return Set not array |
65 |
import org.openide.util.LookupListener; |
|
|
66 |
import org.openide.util.LookupEvent; |
62 |
|
67 |
|
63 |
/** |
68 |
/** |
64 |
* LibraryManager provides registry of the installed libraries. |
69 |
* LibraryManager provides registry of the installed libraries. |
Lines 67-85
Link Here
|
67 |
*/ |
72 |
*/ |
68 |
public final class LibraryManager { |
73 |
public final class LibraryManager { |
69 |
|
74 |
|
|
|
75 |
/** |
76 |
* Property fired when the set of libraries changes. |
77 |
*/ |
70 |
public static final String PROP_LIBRARIES = "libraries"; //NOI18N |
78 |
public static final String PROP_LIBRARIES = "libraries"; //NOI18N |
71 |
|
79 |
|
72 |
private static LibraryManager instance; |
80 |
private static LibraryManager instance; |
73 |
|
81 |
|
74 |
private Lookup.Result<LibraryProvider> result; |
82 |
private Lookup.Result<LibraryProvider> result; |
75 |
private Collection<LibraryProvider> currentStorages = new ArrayList<LibraryProvider>(); |
83 |
private final Collection<LibraryProvider> currentStorages = new ArrayList<LibraryProvider>(); |
76 |
private PropertyChangeListener plistener; |
84 |
private final PropertyChangeListener plistener = new PropertyChangeListener() { |
77 |
private PropertyChangeSupport listeners; |
85 |
public void propertyChange(PropertyChangeEvent evt) { |
|
|
86 |
if (LibraryProvider.PROP_LIBRARIES.equals(evt.getPropertyName())) { |
87 |
resetCache(); |
88 |
} |
89 |
} |
90 |
}; |
91 |
private final PropertyChangeSupport listeners = new PropertyChangeSupport(this); |
92 |
private static final PropertyChangeSupport openLibraryManagerListListeners = |
93 |
new PropertyChangeSupport(LibraryManager.class); |
94 |
private static final PropertyChangeListener AREAL_LIBRARY_PROVIDER_LISTENER = new PropertyChangeListener() { |
95 |
public void propertyChange(PropertyChangeEvent evt) { |
96 |
openLibraryManagerListListeners.firePropertyChange(PROP_OPEN_LIBRARY_MANAGERS, null, null); |
97 |
} |
98 |
}; |
99 |
|
100 |
/** Property fired when list of open library managers changes. */ |
101 |
public static final String PROP_OPEN_LIBRARY_MANAGERS = "openManagers"; // NOI18N |
102 |
private static Lookup.Result<ArealLibraryProvider> areaProvidersLookupResult = null; |
103 |
private static Collection<? extends ArealLibraryProvider> currentAreaProviders = new ArrayList<ArealLibraryProvider>(); |
104 |
|
78 |
private Collection<Library> cache; |
105 |
private Collection<Library> cache; |
79 |
|
106 |
/** null for default manager */ |
|
|
107 |
private final ArealLibraryProvider alp; |
108 |
/** null for default manager */ |
109 |
private final LibraryStorageArea area; |
80 |
|
110 |
|
81 |
private LibraryManager () { |
111 |
private LibraryManager () { |
82 |
this.listeners = new PropertyChangeSupport(this); |
112 |
alp = null; |
|
|
113 |
area = null; |
114 |
} |
115 |
|
116 |
private LibraryManager(ArealLibraryProvider alp, LibraryStorageArea area) { |
117 |
this.alp = alp; |
118 |
this.area = area; |
119 |
LibraryProvider lp = LibraryAccessor.getLibraries(alp, area); |
120 |
lp.addPropertyChangeListener(plistener); |
121 |
currentStorages.add(lp); |
122 |
} |
123 |
|
124 |
/** |
125 |
* Gets a human-readable description of this manager. |
126 |
* This may be used to visually differentiate the global manager from various local managers. |
127 |
* @return a localized display name |
128 |
* @see LibraryStorageArea#getDisplayName |
129 |
* @since org.netbeans.modules.project.libraries/1 1.15 |
130 |
*/ |
131 |
public String getDisplayName() { |
132 |
if (area == null) { |
133 |
return LibrariesModel.GLOBAL_AREA.getDisplayName(); |
134 |
} else { |
135 |
return area.getDisplayName(); |
136 |
} |
137 |
} |
138 |
|
139 |
/** |
140 |
* Gets the location associated with this manager. |
141 |
* @return a location where library definitions are kept, or null in the case of {@link #getDefault} |
142 |
* @see LibraryStorageArea#getLocation |
143 |
* @see #forLocation |
144 |
* @since org.netbeans.modules.project.libraries/1 1.15 |
145 |
*/ |
146 |
public URL getLocation() { |
147 |
return area != null ? area.getLocation() : null; |
83 |
} |
148 |
} |
84 |
|
149 |
|
85 |
/** |
150 |
/** |
Lines 99-142
Link Here
|
99 |
} |
164 |
} |
100 |
|
165 |
|
101 |
/** |
166 |
/** |
102 |
* List all library defined in the IDE. |
167 |
* Lists all libraries defined in this manager. |
103 |
* |
168 |
* @return library definitions (never <code>null</code>) |
104 |
* @return Library[] library definitions never <code>null</code> |
|
|
105 |
*/ |
169 |
*/ |
106 |
public synchronized Library[] getLibraries() { |
170 |
public synchronized Library[] getLibraries() { |
107 |
if (this.cache == null) { |
171 |
if (this.cache == null) { |
108 |
if (this.result == null) { |
172 |
List<Library> l = new ArrayList<Library>(); |
109 |
plistener = new PropertyChangeListener() { |
173 |
if (area == null) { |
110 |
public void propertyChange(PropertyChangeEvent evt) { |
174 |
if (result == null) { |
111 |
resetCache (); |
175 |
result = Lookup.getDefault().lookupResult(LibraryProvider.class); |
|
|
176 |
result.addLookupListener(new LookupListener() { |
177 |
public void resultChanged(LookupEvent ev) { |
178 |
resetCache(); |
179 |
} |
180 |
}); |
181 |
} |
182 |
Collection<? extends LibraryProvider> instances = result.allInstances(); |
183 |
Collection<LibraryProvider> added = new HashSet<LibraryProvider>(instances); |
184 |
added.removeAll(currentStorages); |
185 |
Collection<LibraryProvider> removed = new HashSet<LibraryProvider>(currentStorages); |
186 |
removed.removeAll(instances); |
187 |
currentStorages.clear(); |
188 |
for (LibraryProvider storage : instances) { |
189 |
this.currentStorages.add(storage); |
190 |
for (LibraryImplementation impl : storage.getLibraries()) { |
191 |
l.add(new Library(impl, this)); |
112 |
} |
192 |
} |
113 |
}; |
193 |
} |
114 |
result = Lookup.getDefault().lookupResult(LibraryProvider.class); |
194 |
for (LibraryProvider p : removed) { |
115 |
result.addLookupListener (new LookupListener() { |
195 |
p.removePropertyChangeListener(this.plistener); |
116 |
public void resultChanged(LookupEvent ev) { |
196 |
} |
117 |
resetCache (); |
197 |
for (LibraryProvider p : added) { |
118 |
} |
198 |
p.addPropertyChangeListener(this.plistener); |
119 |
}); |
199 |
} |
120 |
} |
200 |
} else { |
121 |
List<Library> l = new ArrayList<Library>(); |
201 |
for (LibraryImplementation impl : currentStorages.iterator().next().getLibraries()) { |
122 |
Collection<? extends LibraryProvider> instances = result.allInstances(); |
202 |
l.add(new Library(impl, this)); |
123 |
Collection<LibraryProvider> added = new HashSet<LibraryProvider>(instances); |
|
|
124 |
added.removeAll (currentStorages); |
125 |
Collection<LibraryProvider> removed = new HashSet<LibraryProvider>(currentStorages); |
126 |
removed.removeAll (instances); |
127 |
currentStorages.clear(); |
128 |
for (LibraryProvider storage : instances) { |
129 |
this.currentStorages.add (storage); |
130 |
for (LibraryImplementation impl : storage.getLibraries()) { |
131 |
l.add(LibraryFactory.createLibrary(impl)); |
132 |
} |
203 |
} |
133 |
} |
204 |
} |
134 |
for (LibraryProvider p : removed) { |
|
|
135 |
p.removePropertyChangeListener(this.plistener); |
136 |
} |
137 |
for (LibraryProvider p : added) { |
138 |
p.addPropertyChangeListener(this.plistener); |
139 |
} |
140 |
this.cache = l; |
205 |
this.cache = l; |
141 |
} |
206 |
} |
142 |
return this.cache.toArray(new Library[this.cache.size()]); |
207 |
return this.cache.toArray(new Library[this.cache.size()]); |
Lines 160-168
Link Here
|
160 |
* @throws IOException when the library cannot be stored |
225 |
* @throws IOException when the library cannot be stored |
161 |
* @throws IllegalArgumentException if the library is not recognized by any |
226 |
* @throws IllegalArgumentException if the library is not recognized by any |
162 |
* {@link org.netbeans.spi.project.libraries.LibraryTypeProvider} or the library |
227 |
* {@link org.netbeans.spi.project.libraries.LibraryTypeProvider} or the library |
163 |
* of the same name already exists. |
228 |
* of the same name already exists, or if this manager is not {@link #getDefault}. |
164 |
* @since org.netbeans.modules.project.libraries/1 1.14 |
229 |
* @since org.netbeans.modules.project.libraries/1 1.14 |
|
|
230 |
* @deprecated Use {@link #createLibrary} instead, as this properly supports local managers. |
165 |
*/ |
231 |
*/ |
|
|
232 |
@Deprecated |
166 |
public void addLibrary (final Library library) throws IOException, IllegalArgumentException { |
233 |
public void addLibrary (final Library library) throws IOException, IllegalArgumentException { |
167 |
assert library != null; |
234 |
assert library != null; |
168 |
if (LibrariesSupport.getLibraryTypeProvider(library.getType()) == null) { |
235 |
if (LibrariesSupport.getLibraryTypeProvider(library.getType()) == null) { |
Lines 176-182
Link Here
|
176 |
assert providers.size() == 1; |
243 |
assert providers.size() == 1; |
177 |
providers.iterator().next().addLibrary(library.getLibraryImplementation()); |
244 |
providers.iterator().next().addLibrary(library.getLibraryImplementation()); |
178 |
} |
245 |
} |
179 |
|
246 |
|
|
|
247 |
/** |
248 |
* Creates a new library definition and adds it to the list. |
249 |
* @param type the type of library, as in {@link LibraryTypeProvider#getLibraryType} or {@link LibraryImplementation#getType} |
250 |
* @param name the identifying name of the new library (must not duplicate a name already in use by a library in this manager) |
251 |
* @param contents the initial contents of the library's volumes, as a map from volume type to volume content |
252 |
* @return a newly created library |
253 |
* @throws IOException if the new definition could not be stored |
254 |
* @throws IllegalArgumentException if the library type or one of the content volume types is not supported, |
255 |
* or if a library of the same name already exists in this manager |
256 |
* @see ArealLibraryProvider#createLibrary |
257 |
* @since org.netbeans.modules.project.libraries/1 1.15 |
258 |
*/ |
259 |
public Library createLibrary(String type, String name, Map<String,List<URL>> contents) throws IOException { |
260 |
if (getLibrary(name) != null) { |
261 |
throw new IllegalArgumentException("Name already in use: " + name); // NOI18N |
262 |
} |
263 |
LibraryImplementation impl; |
264 |
if (area == null) { |
265 |
LibraryTypeProvider ltp = LibrariesSupport.getLibraryTypeProvider(type); |
266 |
if (ltp == null) { |
267 |
throw new IllegalArgumentException("Trying to add a library of unknown type: " + type); // NOI18N |
268 |
} |
269 |
impl = ltp.createLibrary(); |
270 |
impl.setName(name); |
271 |
for (Map.Entry<String,List<URL>> entry : contents.entrySet()) { |
272 |
impl.setContent(entry.getKey(), entry.getValue()); |
273 |
} |
274 |
Lookup.getDefault().lookup(WritableLibraryProvider.class).addLibrary(impl); |
275 |
} else { |
276 |
impl = LibraryAccessor.createLibrary(alp, type, name, area, contents); |
277 |
} |
278 |
return new Library(impl, this); |
279 |
} |
280 |
|
180 |
/** |
281 |
/** |
181 |
* Removes installed library |
282 |
* Removes installed library |
182 |
* @param library to be removed. |
283 |
* @param library to be removed. |
Lines 187-195
Link Here
|
187 |
*/ |
288 |
*/ |
188 |
public void removeLibrary (final Library library) throws IOException, IllegalArgumentException { |
289 |
public void removeLibrary (final Library library) throws IOException, IllegalArgumentException { |
189 |
assert library != null; |
290 |
assert library != null; |
190 |
final Collection<? extends WritableLibraryProvider> providers = Lookup.getDefault().lookupAll(WritableLibraryProvider.class); |
291 |
if (area == null) { |
191 |
assert providers.size() == 1; |
292 |
final Collection<? extends WritableLibraryProvider> providers = Lookup.getDefault().lookupAll(WritableLibraryProvider.class); |
192 |
providers.iterator().next().removeLibrary(library.getLibraryImplementation()); |
293 |
assert providers.size() == 1; |
|
|
294 |
providers.iterator().next().removeLibrary(library.getLibraryImplementation()); |
295 |
} else { |
296 |
LibraryAccessor.remove(alp, library.getLibraryImplementation()); |
297 |
} |
193 |
} |
298 |
} |
194 |
|
299 |
|
195 |
/** |
300 |
/** |
Lines 229-235
Link Here
|
229 |
return instance; |
334 |
return instance; |
230 |
} |
335 |
} |
231 |
|
336 |
|
|
|
337 |
/** |
338 |
* Gets a library manager which loads library definitions from a particular location. |
339 |
* There is no guarantee that the return value is the same object from call to call with the same location. |
340 |
* @param location any storage location supported by an installed provider |
341 |
* @return a library manager whose {@link #getLocation} matches the supplied location |
342 |
* @throws IllegalArgumentException if no installed provider is able to manage locations of this kind |
343 |
* @see ArealLibraryProvider#loadArea |
344 |
* @see ArealLibraryProvider#getLibraries |
345 |
* @since org.netbeans.modules.project.libraries/1 1.15 |
346 |
*/ |
347 |
public static LibraryManager forLocation(URL location) throws IllegalArgumentException { |
348 |
for (ArealLibraryProvider alp : Lookup.getDefault().lookupAll(ArealLibraryProvider.class)) { |
349 |
LibraryStorageArea area = alp.loadArea(location); |
350 |
if (area != null) { |
351 |
return new LibraryManager(alp, area); |
352 |
} |
353 |
} |
354 |
throw new IllegalArgumentException(location.toExternalForm()); |
355 |
} |
232 |
|
356 |
|
|
|
357 |
/** |
358 |
* Gets an unspecified collection of managers which are somehow to be represented as open. |
359 |
* For example, library storages referred to from open projects might be returned. |
360 |
* You can listen on changes in list of open managers via {@link #addOpenManagersPropertyChangeListener}. |
361 |
* There is no guarantee that the non-default managers are the same objects from call to call |
362 |
* even if the locations remain the same. |
363 |
* @see ArealLibraryProvider#getOpenAreas |
364 |
* @return a set of managers, always including at least {@link #getDefault} |
365 |
* @since org.netbeans.modules.project.libraries/1 1.15 |
366 |
*/ |
367 |
public static Collection<LibraryManager> getOpenManagers() { |
368 |
List<LibraryManager> managers = new ArrayList<LibraryManager>(); |
369 |
managers.add(getDefault()); |
370 |
Set<URL> locations = new HashSet<URL>(); |
371 |
for (ArealLibraryProvider alp : Lookup.getDefault().lookupAll(ArealLibraryProvider.class)) { |
372 |
for (LibraryStorageArea area : LibraryAccessor.getOpenAreas(alp)) { |
373 |
if (locations.add(area.getLocation())) { |
374 |
managers.add(new LibraryManager(alp, area)); |
375 |
} |
376 |
} |
377 |
} |
378 |
for (ArealLibraryProvider alp : Lookup.getDefault().lookupAll(ArealLibraryProvider.class)) { |
379 |
for (URL location : LibrariesModel.createdAreas) { |
380 |
LibraryStorageArea area = alp.loadArea(location); |
381 |
if (area != null) { |
382 |
assert area.getLocation().equals(location) : "Bad location " + area.getLocation() + " does not match " + location + " from " + alp.getClass().getName(); |
383 |
if (locations.add(location)) { |
384 |
managers.add(new LibraryManager(alp, area)); |
385 |
} |
386 |
} |
387 |
} |
388 |
} |
389 |
return managers; |
390 |
} |
391 |
|
392 |
/** |
393 |
* Adds PropertyChangeListener on list of open library managers. |
394 |
* The listener is notified when list of open library managers changes via |
395 |
* {@link #PROP_OPEN_LIBRARY_MANAGERS}. |
396 |
* @param listener to be notified |
397 |
*/ |
398 |
public static synchronized void addOpenManagersPropertyChangeListener (PropertyChangeListener listener) { |
399 |
assert listener != null; |
400 |
if (areaProvidersLookupResult == null) { |
401 |
areaProvidersLookupResult = Lookup.getDefault().lookupResult(ArealLibraryProvider.class); |
402 |
attachListeners(areaProvidersLookupResult.allInstances()); |
403 |
areaProvidersLookupResult.addLookupListener(new LookupListener() { |
404 |
public void resultChanged(LookupEvent ev) { |
405 |
attachListeners(areaProvidersLookupResult.allInstances()); |
406 |
} |
407 |
}); |
408 |
} |
409 |
openLibraryManagerListListeners.addPropertyChangeListener (listener); |
410 |
} |
411 |
|
412 |
private static synchronized void attachListeners(Collection<? extends ArealLibraryProvider> currentProviders) { |
413 |
for (ArealLibraryProvider provider : currentAreaProviders) { |
414 |
provider.removePropertyChangeListener(AREAL_LIBRARY_PROVIDER_LISTENER); |
415 |
} |
416 |
for (ArealLibraryProvider provider : currentProviders) { |
417 |
provider.addPropertyChangeListener(AREAL_LIBRARY_PROVIDER_LISTENER); |
418 |
} |
419 |
currentAreaProviders = currentProviders; |
420 |
} |
421 |
|
422 |
/** |
423 |
* Removes PropertyChangeListener |
424 |
* @param listener |
425 |
*/ |
426 |
public static void removeOpenManagersPropertyChangeListener (PropertyChangeListener listener) { |
427 |
assert listener != null; |
428 |
openLibraryManagerListListeners.removePropertyChangeListener (listener); |
429 |
} |
430 |
|
431 |
@Override |
432 |
public String toString() { |
433 |
URL loc = getLocation(); |
434 |
return "LibraryManager[" + (loc != null ? loc : "default") + "]"; // NOI18N |
435 |
} |
436 |
|
437 |
LibraryStorageArea getArea() { |
438 |
return area; |
439 |
} |
233 |
|
440 |
|
234 |
} // end LibraryManager |
441 |
} // end LibraryManager |
235 |
|
442 |
|