KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > libraries > LibrariesStorage


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.project.libraries;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeSupport JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.io.OutputStreamWriter JavaDoc;
29 import java.io.PrintWriter JavaDoc;
30 import java.net.URL JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Properties JavaDoc;
37 import java.util.ResourceBundle JavaDoc;
38 import java.util.Set JavaDoc;
39 import java.util.StringTokenizer JavaDoc;
40 import java.util.TreeSet JavaDoc;
41 import javax.xml.parsers.ParserConfigurationException JavaDoc;
42 import org.netbeans.spi.project.libraries.LibraryImplementation;
43 import org.netbeans.spi.project.libraries.LibraryTypeProvider;
44 import org.openide.ErrorManager;
45 import org.openide.filesystems.FileChangeAdapter;
46 import org.openide.filesystems.FileEvent;
47 import org.openide.filesystems.FileLock;
48 import org.openide.filesystems.FileObject;
49 import org.openide.filesystems.FileSystem;
50 import org.openide.filesystems.FileUtil;
51 import org.openide.filesystems.Repository;
52 import org.openide.util.NbBundle;
53 import org.openide.xml.XMLUtil;
54 import org.xml.sax.InputSource JavaDoc;
55 import org.xml.sax.SAXException JavaDoc;
56
57 public class LibrariesStorage extends FileChangeAdapter implements WritableLibraryProvider {
58
59     private static final String JavaDoc NB_HOME_PROPERTY = "netbeans.home"; //NOI18N
60
private static final String JavaDoc LIBRARIES_REPOSITORY = "org-netbeans-api-project-libraries/Libraries"; //NOI18N
61
private static final String JavaDoc TIME_STAMPS_FILE = "libraries-timestamps.properties"; //NOI18B
62
private static final String JavaDoc XML_EXT = "xml"; //NOI18N
63

64     // persistent storage, it may be null for before first library is store into storage
65
private FileObject storage = null;
66
67     private Map JavaDoc<String JavaDoc, LibraryImplementation> libraries;
68
69     private Map JavaDoc<String JavaDoc, LibraryImplementation> librariesByFileNames;
70
71     // Library declaraion public ID
72
// i18n bundle
73
private ResourceBundle JavaDoc bundle;
74
75     private PropertyChangeSupport JavaDoc support;
76     
77     //Flag if the storage is initialized
78
//The storage needs to be lazy initialized, it is in lookup
79
private boolean initialized;
80     
81     private Properties JavaDoc timeStamps;
82
83
84     /**
85      * Create libraries that need to be populated later.
86      */

87     public LibrariesStorage() {
88         this.support = new PropertyChangeSupport JavaDoc(this);
89     }
90     
91     /**
92      * Constructor for tests
93      */

94     LibrariesStorage (FileObject storage) {
95         this ();
96         this.storage = storage;
97     }
98
99
100
101     /**
102      * Initialize the default storage.
103      * @return new storage or null on I/O error.
104      */

105     private static final FileObject createStorage () {
106         FileSystem storageFS = Repository.getDefault().getDefaultFileSystem();
107         try {
108             return FileUtil.createFolder(storageFS.getRoot(), LIBRARIES_REPOSITORY);
109         } catch (IOException JavaDoc e) {
110             return null;
111         }
112     }
113
114
115     // scans over storage and fetchs it ((fileset persistence files) into memory
116
// ... note that providers can read their data during getVolume call
117
private void loadFromStorage() {
118         // configure parser
119
libraries = new HashMap JavaDoc<String JavaDoc,LibraryImplementation>();
120         librariesByFileNames = new HashMap JavaDoc<String JavaDoc,LibraryImplementation>();
121         LibraryDeclarationHandlerImpl handler = new LibraryDeclarationHandlerImpl();
122         LibraryDeclarationConvertorImpl convertor = new LibraryDeclarationConvertorImpl();
123         LibraryDeclarationParser parser = new LibraryDeclarationParser(handler,convertor);
124         // parse
125
for (FileObject descriptorFile : storage.getChildren()) {
126             if (XML_EXT.equalsIgnoreCase(descriptorFile.getExt())) {
127                 try {
128                     handler.setLibrary (null);
129                     readLibrary (descriptorFile, parser);
130                     LibraryImplementation impl = handler.getLibrary ();
131                     if (impl != null) {
132                         LibraryTypeProvider provider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (impl.getType());
133                         if (provider == null) {
134                             ErrorManager.getDefault().log(ErrorManager.WARNING, "LibrariesStorage: Can not invoke LibraryTypeProvider.libraryCreated(), the library type provider is unknown."); //NOI18N
135
}
136                         else if (libraries.keySet().contains(impl.getName())) {
137                                 ErrorManager.getDefault().log(ErrorManager.WARNING, "LibrariesStorage: Library \""
138                                     +impl.getName()+"\" is already defined, skeeping the definition from: "
139                                     + FileUtil.getFileDisplayName(descriptorFile));
140                         }
141                         else {
142                             if (!isUpToDate(descriptorFile)) {
143                                 provider.libraryCreated (impl);
144                                 updateTimeStamp(descriptorFile);
145                             }
146                             librariesByFileNames.put(descriptorFile.getPath(),impl);
147                             libraries.put (impl.getName(),impl);
148                         }
149                     }
150                 } catch (SAXException JavaDoc e) {
151                     ErrorManager.getDefault().notify (e);
152                 } catch (ParserConfigurationException JavaDoc e) {
153                     ErrorManager.getDefault().notify (e);
154                 } catch (IOException JavaDoc e) {
155                     ErrorManager.getDefault().notify (e);
156                 } catch (RuntimeException JavaDoc e) {
157                     // Other problem.
158
ErrorManager.getDefault().notify (e);
159                 }
160             }
161         }
162         try {
163             saveTimeStamps();
164         } catch (IOException JavaDoc ioe) {
165             ErrorManager.getDefault().notify(ioe);
166         }
167     }
168     
169     private synchronized void initStorage () {
170         if (!initialized) {
171             if (this.storage == null) {
172                 this.storage = createStorage();
173                 if (storage == null) {
174                     // Storage broken. May happen e.g. inside unit tests.
175
libraries = Collections.emptyMap();
176                     librariesByFileNames = Collections.emptyMap();
177                     initialized = true;
178                     return;
179                 }
180             }
181             this.loadFromStorage();
182             this.storage.addFileChangeListener (this);
183             initialized = true;
184         }
185     }
186
187     private static LibraryImplementation readLibrary (FileObject descriptorFile) throws SAXException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc{
188         return readLibrary (descriptorFile, (LibraryImplementation) null);
189     }
190     
191     private static LibraryImplementation readLibrary (FileObject descriptorFile, LibraryImplementation impl) throws SAXException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc {
192         LibraryDeclarationHandlerImpl handler = new LibraryDeclarationHandlerImpl();
193         LibraryDeclarationConvertorImpl convertor = new LibraryDeclarationConvertorImpl();
194         LibraryDeclarationParser parser = new LibraryDeclarationParser(handler,convertor);
195         handler.setLibrary (impl);
196         readLibrary (descriptorFile, parser);
197         return handler.getLibrary();
198     }
199
200     private static void readLibrary (FileObject descriptorFile, LibraryDeclarationParser parser) throws SAXException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc {
201         URL JavaDoc baseURL = descriptorFile.getURL();
202         InputSource JavaDoc input = new InputSource JavaDoc(baseURL.toExternalForm());
203         input.setByteStream(descriptorFile.getInputStream()); // #33554 workaround
204
try {
205             parser.parse(input);
206         } catch (SAXException JavaDoc e) {
207             ErrorManager.getDefault().annotate(e, ErrorManager.UNKNOWN, "From " + baseURL, null, null, null);
208             throw e;
209         }
210     }
211
212     private void writeLibrary (final FileObject storage, final LibraryImplementation library) throws IOException JavaDoc {
213         storage.getFileSystem().runAtomicAction(
214                 new FileSystem.AtomicAction() {
215                     public void run() throws IOException JavaDoc {
216                         String JavaDoc libraryType = library.getType ();
217                         LibraryTypeProvider libraryTypeProvider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (libraryType);
218                         if (libraryTypeProvider == null) {
219                             ErrorManager.getDefault().log (ErrorManager.WARNING, "LibrariesStorage: Cannot store library, the library type is not recognized by any of installed LibraryTypeProviders."); //NOI18N
220
return;
221                         }
222                         FileObject fo = storage.createData (library.getName(),"xml"); //NOI18N
223
writeLibraryDefinition (fo, library, libraryTypeProvider);
224                     }
225                 }
226         );
227     }
228
229     private static void writeLibraryDefinition (final FileObject definitionFile, final LibraryImplementation library, final LibraryTypeProvider libraryTypeProvider) throws IOException JavaDoc {
230         FileLock lock = null;
231         PrintWriter JavaDoc out = null;
232         try {
233             lock = definitionFile.lock();
234             out = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(definitionFile.getOutputStream (lock),"UTF-8"));
235             // XXX use DOM and XMLUtil.write instead
236
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); //NOI18N
237
out.println("<!DOCTYPE library PUBLIC \"-//NetBeans//DTD Library Declaration 1.0//EN\" \"http://www.netbeans.org/dtds/library-declaration-1_0.dtd\">"); //NOI18N
238
out.println("<library version=\"1.0\">"); //NOI18N
239
out.println("\t<name>"+library.getName()+"</name>"); //NOI18N
240
out.println("\t<type>"+library.getType()+"</type>");
241             String JavaDoc description = library.getDescription();
242             if (description != null && description.length() > 0) {
243                 out.println("\t<description>"+description+"</description>"); //NOI18N
244
}
245             String JavaDoc localizingBundle = library.getLocalizingBundle();
246             if (localizingBundle != null && localizingBundle.length() > 0) {
247                 out.println("\t<localizing-bundle>"+XMLUtil.toElementContent(localizingBundle)+"</localizing-bundle>"); //NOI18N
248
}
249             String JavaDoc[] volumeTypes = libraryTypeProvider.getSupportedVolumeTypes ();
250             for (String JavaDoc vtype : volumeTypes) {
251                 out.println("\t<volume>"); //NOI18N
252
out.println ("\t\t<type>" + vtype + "</type>"); //NOI18N
253
List JavaDoc<URL JavaDoc> volume = library.getContent(vtype);
254                 if (volume != null) {
255                     //If null -> broken library, repair it.
256
for (URL JavaDoc url : volume) {
257                         out.println("\t\t<resource>"+XMLUtil.toElementContent(url.toExternalForm())+"</resource>"); //NOI18N
258
}
259                 }
260                 out.println("\t</volume>"); //NOI18N
261
}
262             out.println("</library>"); //NOI18N
263
} finally {
264             if (out != null)
265                 out.close();
266             if (lock != null)
267                 lock.releaseLock();
268         }
269     }
270
271
272     private void fireLibrariesChanged () {
273         this.support.firePropertyChange(PROP_LIBRARIES,null,null);
274     }
275
276
277     public final void addPropertyChangeListener (PropertyChangeListener JavaDoc listener) {
278         this.support.addPropertyChangeListener(listener);
279     }
280
281
282     public final void removePropertyChangeListener (PropertyChangeListener JavaDoc listener) {
283         this.support.removePropertyChangeListener(listener);
284     }
285
286     /**
287      * Return all libraries in memory.
288      */

289     public final LibraryImplementation[] getLibraries() {
290         this.initStorage();
291         assert this.storage != null : "Storage is not initialized";
292         return libraries.values().toArray(new LibraryImplementation[libraries.size()]);
293     } // end getLibraries
294

295
296     public void addLibrary (LibraryImplementation library) throws IOException JavaDoc {
297         this.initStorage();
298         assert this.storage != null : "Storage is not initialized";
299         writeLibrary(this.storage,library);
300     }
301
302     public void removeLibrary (LibraryImplementation library) throws IOException JavaDoc {
303         this.initStorage();
304         assert this.storage != null : "Storage is not initialized";
305         for (String JavaDoc key : librariesByFileNames.keySet()) {
306             LibraryImplementation lib = this.librariesByFileNames.get(key);
307             if (library.equals (lib)) {
308                 FileObject fo = this.storage.getFileSystem().findResource (key);
309                 if (fo != null) {
310                     fo.delete();
311                     return;
312                 }
313             }
314         }
315     }
316
317     public void updateLibrary(final LibraryImplementation oldLibrary, final LibraryImplementation newLibrary) throws IOException JavaDoc {
318         this.initStorage();
319         assert this.storage != null : "Storage is not initialized";
320         for (String JavaDoc key : librariesByFileNames.keySet()) {
321             LibraryImplementation lib = librariesByFileNames.get(key);
322             if (oldLibrary.equals(lib)) {
323                 final FileObject fo = this.storage.getFileSystem().findResource(key);
324                 if (fo != null) {
325                     String JavaDoc libraryType = newLibrary.getType ();
326                     final LibraryTypeProvider libraryTypeProvider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (libraryType);
327                     if (libraryTypeProvider == null) {
328                         ErrorManager.getDefault().log (ErrorManager.WARNING, "LibrariesStorageL Cannot store library, the library type is not recognized by any of installed LibraryTypeProviders."); //NOI18N
329
return;
330                     }
331                     this.storage.getFileSystem().runAtomicAction(
332                             new FileSystem.AtomicAction() {
333                                 public void run() throws IOException JavaDoc {
334                                     writeLibraryDefinition (fo, newLibrary, libraryTypeProvider);
335                                 }
336                             }
337                     );
338                 }
339             }
340         }
341     }
342
343
344     public void fileDataCreated(FileEvent fe) {
345         FileObject fo = fe.getFile();
346         try {
347             final LibraryImplementation impl = readLibrary (fo);
348             if (impl != null) {
349                 LibraryTypeProvider provider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (impl.getType());
350                 if (provider == null) {
351                     ErrorManager.getDefault().log(ErrorManager.WARNING, "LibrariesStorage: Can not invoke LibraryTypeProvider.libraryCreated(), the library type provider is unknown."); //NOI18N
352
}
353                 else {
354                     synchronized (this) {
355                         this.libraries.put (impl.getName(), impl);
356                         this.librariesByFileNames.put (fo.getPath(), impl);
357                     }
358                     //Has to be called outside the synchronized block,
359
// The code is provided by LibraryType implementator and can fire events -> may cause deadlocks
360
try {
361                         provider.libraryCreated (impl);
362                         updateTimeStamp(fo);
363                         saveTimeStamps();
364                     } catch (RuntimeException JavaDoc e) {
365                         String JavaDoc message = NbBundle.getMessage(LibrariesStorage.class,"MSG_libraryCreatedError");
366                         ErrorManager.getDefault().notify(ErrorManager.getDefault().annotate(e,message));
367                     }
368                     this.fireLibrariesChanged();
369                 }
370             }
371         } catch (SAXException JavaDoc e) {
372             ErrorManager.getDefault().notify (e);
373         } catch (ParserConfigurationException JavaDoc e) {
374             ErrorManager.getDefault().notify (e);
375         } catch (IOException JavaDoc e) {
376             ErrorManager.getDefault().notify (e);
377         }
378     }
379
380     public void fileDeleted(FileEvent fe) {
381         String JavaDoc fileName = fe.getFile().getPath();
382         LibraryImplementation impl;
383         synchronized (this) {
384             impl = this.librariesByFileNames.remove(fileName);
385             if (impl != null) {
386                 this.libraries.remove (impl.getName());
387             }
388         }
389         if (impl != null) {
390             LibraryTypeProvider provider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (impl.getType());
391             if (provider == null) {
392                 ErrorManager.getDefault().log(ErrorManager.WARNING, "LibrariesStorage: Cannot invoke LibraryTypeProvider.libraryDeleted(), the library type provider is unknown."); //NOI18N
393
}
394             else {
395                 //Has to be called outside the synchronized block,
396
// The code is provided by LibraryType implementator and can fire events -> may cause deadlocks
397
try {
398                     provider.libraryDeleted (impl);
399                 } catch (RuntimeException JavaDoc e) {
400                     String JavaDoc message = NbBundle.getMessage(LibrariesStorage.class,"MSG_libraryDeletedError");
401                     ErrorManager.getDefault().notify(ErrorManager.getDefault().annotate(e,message));
402                 }
403             }
404             this.fireLibrariesChanged();
405         }
406     }
407
408     public void fileChanged(FileEvent fe) {
409         FileObject definitionFile = fe.getFile();
410         String JavaDoc fileName = definitionFile.getPath();
411         LibraryImplementation impl;
412         synchronized (this) {
413             impl = this.librariesByFileNames.get(fileName);
414         }
415         if (impl != null) {
416             try {
417                 readLibrary (definitionFile, impl);
418                 LibraryTypeProvider provider = LibraryTypeRegistry.getDefault().getLibraryTypeProvider (impl.getType());
419                 if (provider == null) {
420                     ErrorManager.getDefault().log(ErrorManager.WARNING, "LibrariesStorage: Can not invoke LibraryTypeProvider.libraryCreated(), the library type provider is unknown."); //NOI18N
421
}
422                 try {
423                     //TODO: LibraryTypeProvider should be extended by libraryUpdated method
424
provider.libraryCreated (impl);
425                     updateTimeStamp(definitionFile);
426                     saveTimeStamps();
427                 } catch (RuntimeException JavaDoc e) {
428                     String JavaDoc message = NbBundle.getMessage(LibrariesStorage.class,"MSG_libraryCreatedError");
429                     ErrorManager.getDefault().notify(ErrorManager.getDefault().annotate(e,message));
430                 }
431             } catch (SAXException JavaDoc se) {
432                 ErrorManager.getDefault().notify(se);
433             } catch (ParserConfigurationException JavaDoc pce) {
434                 ErrorManager.getDefault().notify(pce);
435             } catch (IOException JavaDoc ioe) {
436                 ErrorManager.getDefault().notify(ioe);
437             }
438         }
439     }
440
441     protected final ResourceBundle JavaDoc getBundle() {
442         if (bundle == null) {
443             bundle = NbBundle.getBundle(LibrariesStorage.class);
444         }
445         return bundle;
446     }
447     
448     private boolean isUpToDate (FileObject libraryDefinition) {
449         Properties JavaDoc timeStamps = getTimeStamps();
450         String JavaDoc ts = (String JavaDoc) timeStamps.get (libraryDefinition.getNameExt());
451         return ts == null ? false : Long.parseLong(ts) >= libraryDefinition.lastModified().getTime();
452     }
453
454     private void updateTimeStamp (FileObject libraryDefinition) {
455         Properties JavaDoc timeStamps = getTimeStamps();
456         timeStamps.put(libraryDefinition.getNameExt(), Long.toString(libraryDefinition.lastModified().getTime()));
457     }
458     
459     private void saveTimeStamps () throws IOException JavaDoc {
460         if (this.storage != null) {
461             Properties JavaDoc timeStamps = getTimeStamps();
462             if (timeStamps.get(NB_HOME_PROPERTY) == null) {
463                 String JavaDoc currNbLoc = getNBRoots();
464                 timeStamps.put(NB_HOME_PROPERTY,currNbLoc);
465             }
466             FileObject parent = storage.getParent();
467             FileObject timeStampFile = parent.getFileObject(TIME_STAMPS_FILE);
468             if (timeStampFile == null) {
469                 timeStampFile = parent.createData(TIME_STAMPS_FILE);
470             }
471             FileLock lock = timeStampFile.lock();
472             try {
473                 OutputStream JavaDoc out = timeStampFile.getOutputStream(lock);
474                 try {
475                     timeStamps.store (out, null);
476                 } finally {
477                     out.close();
478                 }
479             } finally {
480                 lock.releaseLock();
481             }
482         }
483     }
484     
485     private Properties JavaDoc getTimeStamps () {
486         if (this.timeStamps == null) {
487             this.timeStamps = new Properties JavaDoc();
488             if (this.storage != null) {
489                 FileObject timeStampFile = storage.getParent().getFileObject(TIME_STAMPS_FILE);
490                 if (timeStampFile != null) {
491                     try {
492                         InputStream JavaDoc in = timeStampFile.getInputStream();
493                         try {
494                             this.timeStamps.load (in);
495                         } finally {
496                             in.close();
497                         }
498                         String JavaDoc nbLoc = (String JavaDoc) this.timeStamps.get (NB_HOME_PROPERTY);
499                         String JavaDoc currNbLoc = getNBRoots ();
500                         if (nbLoc == null || !nbLoc.equals (currNbLoc)) {
501                             this.timeStamps.clear();
502                         }
503                     } catch (IOException JavaDoc ioe) {
504                         ErrorManager.getDefault().notify(ioe);
505                     }
506                 }
507             }
508         }
509         return this.timeStamps;
510     }
511     
512     private static String JavaDoc getNBRoots () {
513         Set JavaDoc<String JavaDoc> result = new TreeSet JavaDoc<String JavaDoc>();
514         String JavaDoc currentNbLoc = System.getProperty ("netbeans.home"); //NOI18N
515
if (currentNbLoc != null) {
516             File JavaDoc f = FileUtil.normalizeFile(new File JavaDoc (currentNbLoc));
517             if (f.isDirectory()) {
518                 result.add (f.getAbsolutePath());
519             }
520         }
521         currentNbLoc = System.getProperty ("netbeans.dirs"); //NOI18N
522
if (currentNbLoc != null) {
523             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(currentNbLoc, File.pathSeparator);
524             while (tok.hasMoreTokens()) {
525                  File JavaDoc f = FileUtil.normalizeFile(new File JavaDoc(tok.nextToken()));
526                  result.add(f.getAbsolutePath());
527             }
528         }
529         StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
530         for (Iterator JavaDoc<String JavaDoc> it = result.iterator(); it.hasNext();) {
531             sb.append(it.next());
532             if (it.hasNext()) {
533                 sb.append(":"); //NOI18N
534
}
535         }
536         return sb.toString();
537     }
538
539 }
540
Popular Tags