1 19 20 package org.netbeans.modules.javadoc.search; 21 import java.beans.PropertyChangeEvent ; 22 23 import java.beans.PropertyChangeListener ; 24 25 26 import java.net.URL ; 27 import java.util.ArrayList ; 28 import java.util.Arrays ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.LinkedList ; 32 import java.util.List ; 33 import java.util.Set ; 34 import java.util.StringTokenizer ; 35 36 import java.io.Reader ; 37 import java.io.IOException ; 38 import java.io.BufferedReader ; 39 import java.io.InputStreamReader ; 40 import javax.swing.event.ChangeEvent ; 41 42 import javax.swing.event.ChangeListener ; 43 import javax.swing.text.html.HTMLEditorKit ; 44 import javax.swing.text.html.HTML ; 45 import javax.swing.text.html.parser.ParserDelegator ; 46 import javax.swing.text.MutableAttributeSet ; 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 68 public class JavadocRegistry implements GlobalPathRegistryListener, ChangeListener , PropertyChangeListener { 69 70 private static JavadocRegistry INSTANCE; 71 72 73 private GlobalPathRegistry regs; 74 private ArrayList listeners; 75 private Set results; 76 private ClassPath docRoots; 77 private Set classpaths; 78 79 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 94 public FileObject[] getDocRoots() { 95 synchronized (this) { 96 if (this.docRoots != null) { 97 return this.docRoots.getRoots(); 98 } 99 } 100 Set _classpaths = new HashSet (); 104 Set _results = new HashSet (); 105 Set s = readRoots(this, _classpaths, _results); 106 synchronized (this) { 107 if (this.docRoots == null) { 108 this.docRoots = ClassPathSupport.createClassPath((URL [])s.toArray(new URL [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 encoding = getDocEncoding (apidocRoot); 120 Lookup.Result result = Lookup.getDefault().lookup(new Lookup.Template(JavadocSearchType.class)); 121 for (Iterator 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 132 private static Set readRoots( 133 JavadocRegistry jdr, 134 Set classpaths, 135 Set results) { 136 137 Set roots = new HashSet (); 138 List paths = new LinkedList (); 139 paths.addAll( jdr.regs.getPaths( ClassPath.COMPILE ) ); 140 paths.addAll( jdr.regs.getPaths( ClassPath.BOOT ) ); 141 for( Iterator it = paths.iterator(); it.hasNext(); ) { 142 ClassPath ccp = (ClassPath)it.next(); 143 classpaths.add (ccp); 144 List ccpRoots = ccp.entries(); 146 147 for (Iterator it2 = ccpRoots.iterator(); it2.hasNext(); ) { 148 ClassPath.Entry ccpRoot = (ClassPath.Entry) it2.next (); 149 JavadocForBinaryQuery.Result result = JavadocForBinaryQuery.findJavadoc(ccpRoot.getURL()); 151 results.add (result); 152 URL [] jdRoots = result.getRoots(); 153 roots.addAll (Arrays.asList(jdRoots)); 154 } 155 } 156 return roots; 158 } 159 160 private static void registerListeners( 161 JavadocRegistry jdr, 162 Set classpaths, 163 Set results, 164 ClassPath docRoots) { 165 166 for (Iterator it = classpaths.iterator(); it.hasNext();) { 167 ClassPath cpath = (ClassPath) it.next(); 168 cpath.addPropertyChangeListener(jdr); 169 } 170 for (Iterator 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 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 e) { 199 this.throwCache (); 200 this.fireChange (); 201 } 202 203 204 205 public synchronized void addChangeListener (ChangeListener l) { 206 assert l != null : "Listener can not be null."; if (this.listeners == null) { 208 this.listeners = new ArrayList (); 209 } 210 this.listeners.add (l); 211 } 212 213 public synchronized void removeChangeListener (ChangeListener l) { 214 assert l != null : "Listener can not be null."; if (this.listeners == null) { 216 return; 217 } 218 this.listeners.remove (l); 219 } 220 221 private void fireChange () { 222 Iterator it = null; 223 synchronized (this) { 224 if (this.listeners == null) { 225 return; 226 } 227 it = ((ArrayList )this.listeners.clone()).iterator(); 228 } 229 ChangeEvent event = new ChangeEvent (this); 230 while (it.hasNext()) { 231 ((ChangeListener )it.next()).stateChanged(event); 232 } 233 } 234 235 private synchronized void throwCache () { 236 if (this.classpaths != null) { 238 for (Iterator it = this.classpaths.iterator(); it.hasNext();) { 239 ClassPath cp = (ClassPath) it.next (); 240 cp.removePropertyChangeListener(this); 241 it.remove (); 242 } 243 } 244 if (this.results != null) { 246 for (Iterator it = this.results.iterator(); it.hasNext();) { 247 JavadocForBinaryQuery.Result result = (JavadocForBinaryQuery.Result) it.next (); 248 result.removeChangeListener (this); 249 it.remove (); 250 } 251 } 252 if (this.docRoots != null) { 254 this.docRoots.removePropertyChangeListener(this); 255 this.docRoots = null; 256 } 257 } 258 259 260 private String getDocEncoding (FileObject root) { 261 assert root != null && root.isFolder(); 262 FileObject fo = root.getFileObject("index-all.html"); if (fo == null) { 264 fo = root.getFileObject("index-files"); if (fo == null) { 266 return null; 267 } 268 fo = fo.getFileObject("index-1.html"); if (fo == null) { 270 return null; 271 } 272 } 273 ParserDelegator pd = new ParserDelegator (); 274 try { 275 BufferedReader in = new BufferedReader ( new InputStreamReader ( fo.getInputStream () )); 276 EncodingCallback ecb = new EncodingCallback (in); 277 try { 278 pd.parse( in, ecb, true ); 279 } catch (IOException ioe) { 280 } finally { 282 in.close (); 283 } 284 return ecb.getEncoding (); 285 } catch (IOException ioe) { 286 ErrorManager.getDefault().notify (ioe); 287 } 288 return null; 289 } 290 291 292 293 private static class EncodingCallback extends HTMLEditorKit.ParserCallback { 294 295 296 private Reader in; 297 private String encoding; 298 299 public EncodingCallback (Reader in) { 300 this.in = in; 301 } 302 303 304 public String getEncoding () { 305 return this.encoding; 306 } 307 308 309 public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) { 310 if (t == HTML.Tag.META) { 311 String value = (String ) a.getAttribute(HTML.Attribute.CONTENT); 312 if (value != null) { 313 StringTokenizer tk = new StringTokenizer (value,";"); while (tk.hasMoreTokens()) { 315 String str = tk.nextToken().trim(); 316 if (str.startsWith("charset")) { 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 ioe) {} 323 return; 324 } 325 } 326 } 327 } 328 } 329 } 330 331 public void handleStartTag(javax.swing.text.html.HTML.Tag t, javax.swing.text.MutableAttributeSet a, int pos) { 332 if (t == HTML.Tag.BODY) { 333 try { 334 this.in.close (); 335 } catch (IOException ioe) {} 336 } 337 } 338 } 339 340 } 341 | Popular Tags |