KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javadoc > search > JavadocRegistry


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.javadoc.search;
21 import java.beans.PropertyChangeEvent JavaDoc;
22
23 import java.beans.PropertyChangeListener JavaDoc;
24
25
26 import java.net.URL JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.LinkedList JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35
36 import java.io.Reader JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.BufferedReader JavaDoc;
39 import java.io.InputStreamReader JavaDoc;
40 import javax.swing.event.ChangeEvent JavaDoc;
41
42 import javax.swing.event.ChangeListener JavaDoc;
43 import javax.swing.text.html.HTMLEditorKit JavaDoc;
44 import javax.swing.text.html.HTML JavaDoc;
45 import javax.swing.text.html.parser.ParserDelegator JavaDoc;
46 import javax.swing.text.MutableAttributeSet JavaDoc;
47
48 import org.netbeans.api.java.classpath.ClassPath;
49 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
50
51 import org.openide.filesystems.FileObject;
52
53 import org.netbeans.api.java.classpath.GlobalPathRegistry;
54 import org.netbeans.api.java.classpath.GlobalPathRegistryEvent;
55
56 import org.netbeans.api.java.classpath.GlobalPathRegistryListener;
57
58 import org.netbeans.api.java.queries.JavadocForBinaryQuery;
59 import org.openide.ErrorManager;
60 import org.openide.filesystems.URLMapper;
61 import org.openide.util.Lookup;
62
63 /**
64  * Class which is able to serve index files of Javadoc for all
65  * currently used Javadoc documentation sets.
66  * @author Petr Hrebejk
67  */

68 public class JavadocRegistry implements GlobalPathRegistryListener, ChangeListener JavaDoc, PropertyChangeListener JavaDoc {
69         
70     private static JavadocRegistry INSTANCE;
71
72     
73     private GlobalPathRegistry regs;
74     private ArrayList JavaDoc listeners;
75     private Set JavaDoc/*<JavadocForBinaryQuery.Result>*/ results;
76     private ClassPath docRoots;
77     private Set JavaDoc/*ClassPath*/ classpaths;
78     
79     /** Creates a new instance of JavadocRegistry */
80     private JavadocRegistry() {
81         this.regs = GlobalPathRegistry.getDefault ();
82         this.regs.addGlobalPathRegistryListener(this);
83     }
84     
85     public static synchronized JavadocRegistry getDefault() {
86         if ( INSTANCE == null ) {
87             INSTANCE = new JavadocRegistry();
88         }
89         return INSTANCE;
90     }
91
92     /** Returns Array of the Javadoc Index roots
93      */

94     public FileObject[] getDocRoots() {
95         synchronized (this) {
96             if (this.docRoots != null) {
97                 return this.docRoots.getRoots();
98             }
99         }
100         //XXX must be called out of synchronized block to prevent
101
// deadlock. throwCache is called under the ProjectManager.mutex
102
// write lock and Project's SFBQI requires the ProjectManager.mutex readLock
103
Set JavaDoc/*<ClassPath>*/ _classpaths = new HashSet JavaDoc/*<ClassPath>*/();
104         Set JavaDoc/*<JavadocForBinaryQuery.Result>*/ _results = new HashSet JavaDoc/*<JavadocForBinaryQuery.Result>*/();
105         Set JavaDoc/*<URL>*/ s = readRoots(this, _classpaths, _results);
106         synchronized (this) {
107             if (this.docRoots == null) {
108                 this.docRoots = ClassPathSupport.createClassPath((URL JavaDoc[])s.toArray(new URL JavaDoc[s.size()]));
109                 this.classpaths = _classpaths;
110                 this.results = _results;
111                 registerListeners(this, _classpaths, _results, this.docRoots);
112             }
113             return this.docRoots.getRoots();
114         }
115     }
116     
117     
118     public JavadocSearchType findSearchType( FileObject apidocRoot ) {
119         String JavaDoc encoding = getDocEncoding (apidocRoot);
120         Lookup.Result result = Lookup.getDefault().lookup(new Lookup.Template(JavadocSearchType.class));
121         for (Iterator JavaDoc it = result.allInstances().iterator(); it.hasNext();) {
122             JavadocSearchType jdst = (JavadocSearchType) it.next ();
123             if (jdst.accepts(apidocRoot, encoding)) {
124                 return jdst;
125             }
126         }
127         return null;
128     }
129         
130     // Private methods ---------------------------------------------------------
131

132     private static Set JavaDoc/*<FileObject>*/ readRoots(
133             JavadocRegistry jdr,
134             Set JavaDoc/*<ClassPath>*/ classpaths,
135             Set JavaDoc/*<JavadocForBinaryQuery.Result>*/ results) {
136         
137         Set JavaDoc roots = new HashSet JavaDoc ();
138         List JavaDoc paths = new LinkedList JavaDoc();
139         paths.addAll( jdr.regs.getPaths( ClassPath.COMPILE ) );
140         paths.addAll( jdr.regs.getPaths( ClassPath.BOOT ) );
141         for( Iterator JavaDoc it = paths.iterator(); it.hasNext(); ) {
142             ClassPath ccp = (ClassPath)it.next();
143             classpaths.add (ccp);
144             //System.out.println("CCP " + ccp );
145
List JavaDoc/*<ClassPath.Entry>*/ ccpRoots = ccp.entries();
146             
147             for (Iterator JavaDoc it2 = ccpRoots.iterator(); it2.hasNext(); ) {
148                 ClassPath.Entry ccpRoot = (ClassPath.Entry) it2.next ();
149                 //System.out.println(" CCPR " + ccpRoot.getURL());
150
JavadocForBinaryQuery.Result result = JavadocForBinaryQuery.findJavadoc(ccpRoot.getURL());
151                 results.add (result);
152                 URL JavaDoc[] jdRoots = result.getRoots();
153                 roots.addAll (Arrays.asList(jdRoots));
154             }
155         }
156         //System.out.println("roots=" + roots);
157
return roots;
158     }
159     
160     private static void registerListeners(
161             JavadocRegistry jdr,
162             Set JavaDoc/*<ClassPath>*/ classpaths,
163             Set JavaDoc/*<JavadocForBinaryQuery.Result>*/ results,
164             ClassPath docRoots) {
165         
166         for (Iterator JavaDoc it = classpaths.iterator(); it.hasNext();) {
167             ClassPath cpath = (ClassPath) it.next();
168             cpath.addPropertyChangeListener(jdr);
169         }
170         for (Iterator JavaDoc it = results.iterator(); it.hasNext();) {
171             JavadocForBinaryQuery.Result result = (JavadocForBinaryQuery.Result) it.next();
172             result.addChangeListener(jdr);
173         }
174         
175         docRoots.addPropertyChangeListener (jdr);
176         
177     }
178
179     public void pathsAdded(GlobalPathRegistryEvent event) {
180         this.throwCache ();
181         this.fireChange ();
182     }
183
184     public void pathsRemoved(GlobalPathRegistryEvent event) {
185         this.throwCache ();
186         this.fireChange ();
187     }
188     
189     public void propertyChange (PropertyChangeEvent JavaDoc event) {
190         if (ClassPath.PROP_ENTRIES.equals (event.getPropertyName()) ||
191             event.getSource() == this.docRoots) {
192             this.throwCache ();
193             this.fireChange ();
194         }
195     }
196     
197     
198     public void stateChanged(javax.swing.event.ChangeEvent JavaDoc e) {
199         this.throwCache ();
200         this.fireChange ();
201     }
202
203     
204     
205     public synchronized void addChangeListener (ChangeListener JavaDoc l) {
206         assert l != null : "Listener can not be null."; //NOI18N
207
if (this.listeners == null) {
208             this.listeners = new ArrayList JavaDoc ();
209         }
210         this.listeners.add (l);
211     }
212     
213     public synchronized void removeChangeListener (ChangeListener JavaDoc l) {
214         assert l != null : "Listener can not be null."; //NOI18N
215
if (this.listeners == null) {
216             return;
217         }
218         this.listeners.remove (l);
219     }
220     
221     private void fireChange () {
222         Iterator JavaDoc it = null;
223         synchronized (this) {
224             if (this.listeners == null) {
225                 return;
226             }
227             it = ((ArrayList JavaDoc)this.listeners.clone()).iterator();
228         }
229         ChangeEvent JavaDoc event = new ChangeEvent JavaDoc (this);
230         while (it.hasNext()) {
231             ((ChangeListener JavaDoc)it.next()).stateChanged(event);
232         }
233     }
234     
235     private synchronized void throwCache () {
236         //Unregister itself from classpaths, not interested in events
237
if (this.classpaths != null) {
238             for (Iterator JavaDoc it = this.classpaths.iterator(); it.hasNext();) {
239                 ClassPath cp = (ClassPath) it.next ();
240                 cp.removePropertyChangeListener(this);
241                 it.remove ();
242             }
243         }
244         //Unregister itself from results, not interested in events
245
if (this.results != null) {
246             for (Iterator JavaDoc it = this.results.iterator(); it.hasNext();) {
247                 JavadocForBinaryQuery.Result result = (JavadocForBinaryQuery.Result) it.next ();
248                 result.removeChangeListener (this);
249                 it.remove ();
250             }
251         }
252         //Unregister listener from docRoots
253
if (this.docRoots != null) {
254             this.docRoots.removePropertyChangeListener(this);
255             this.docRoots = null;
256         }
257     }
258
259
260     private String JavaDoc getDocEncoding (FileObject root) {
261          assert root != null && root.isFolder();
262         FileObject fo = root.getFileObject("index-all.html"); //NOI18N
263
if (fo == null) {
264             fo = root.getFileObject("index-files"); //NOI18N
265
if (fo == null) {
266                 return null;
267             }
268             fo = fo.getFileObject("index-1.html"); //NOI18N
269
if (fo == null) {
270                 return null;
271             }
272         }
273         ParserDelegator JavaDoc pd = new ParserDelegator JavaDoc();
274         try {
275             BufferedReader JavaDoc in = new BufferedReader JavaDoc( new InputStreamReader JavaDoc( fo.getInputStream () ));
276             EncodingCallback ecb = new EncodingCallback (in);
277             try {
278                 pd.parse( in, ecb, true );
279             } catch (IOException JavaDoc ioe) {
280                 //Do nothing
281
} finally {
282                in.close ();
283             }
284             return ecb.getEncoding ();
285         } catch (IOException JavaDoc ioe) {
286             ErrorManager.getDefault().notify (ioe);
287         }
288         return null;
289     }
290
291
292
293     private static class EncodingCallback extends HTMLEditorKit.ParserCallback JavaDoc {
294
295
296         private Reader JavaDoc in;
297         private String JavaDoc encoding;
298
299         public EncodingCallback (Reader JavaDoc in) {
300             this.in = in;
301         }
302
303
304         public String JavaDoc getEncoding () {
305             return this.encoding;
306         }
307
308
309         public void handleSimpleTag(HTML.Tag JavaDoc t, MutableAttributeSet JavaDoc a, int pos) {
310             if (t == HTML.Tag.META) {
311                 String JavaDoc value = (String JavaDoc) a.getAttribute(HTML.Attribute.CONTENT);
312                 if (value != null) {
313                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(value,";"); // NOI18N
314
while (tk.hasMoreTokens()) {
315                         String JavaDoc str = tk.nextToken().trim();
316                         if (str.startsWith("charset")) { //NOI18N
317
str = str.substring(7).trim();
318                             if (str.charAt(0)=='=') {
319                                 this.encoding = str.substring(1).trim();
320                                 try {
321                                     this.in.close();
322                                 } catch (IOException JavaDoc ioe) {/*Ignore it*/}
323                                 return;
324                             }
325                         }
326                     }
327                 }
328             }
329         }
330
331         public void handleStartTag(javax.swing.text.html.HTML.Tag t, javax.swing.text.MutableAttributeSet JavaDoc a, int pos) {
332             if (t == HTML.Tag.BODY) {
333                 try {
334                     this.in.close ();
335                 } catch (IOException JavaDoc ioe) {/*Ignore it*/}
336             }
337         }
338     }
339
340 }
341
Popular Tags