1 19 20 package org.netbeans.modules.xml.tax.parser; 21 22 import java.io.IOException ; 23 import java.net.URL ; 24 import java.text.MessageFormat ; 25 import org.netbeans.api.xml.services.UserCatalog; 26 import org.netbeans.tax.io.TreeBuilder; 27 import org.netbeans.tax.io.TreeInputSource; 28 import org.netbeans.tax.io.TreeStreamBuilderErrorHandler; 29 import org.openide.ErrorManager; 30 import org.openide.awt.StatusDisplayer; 31 import org.xml.sax.EntityResolver ; 32 import org.xml.sax.InputSource ; 33 import org.xml.sax.SAXException ; 34 35 50 public class TreeStreamSource implements TreeInputSource { 51 52 private static final String BUILDER_IMPL = "org.netbeans.tax.io.XNIBuilder"; 54 55 56 private InputSource inputSource; 57 58 private Class buildClass; 59 60 private ErrorHolder errorHolder; 61 62 66 67 public TreeStreamSource (Class buildClass, InputSource inputSource, URL url) { 68 this.buildClass = buildClass; 69 this.inputSource = inputSource; 70 this.errorHolder = new ErrorHolder(); 71 } 72 73 74 78 80 public TreeBuilder getBuilder () { 81 return getImplementation(); 82 } 83 84 85 89 92 99 100 101 104 112 113 116 private TreeBuilder getImplementation () { 117 118 ClassLoader loader; 119 120 if (Boolean.getBoolean("netbeans.tax.use_private_xni_impl")) { loader = ParserLoader.getInstance(); 122 if (loader == null) { 123 if ( Util.THIS.isLoggable() ) Util.THIS.debug("Can not get loader."); 125 return null; 126 } 127 } else { 128 loader = TreeBuilder.class.getClassLoader(); } 130 131 Class impl_c = null; 132 try { 133 impl_c = loader.loadClass(BUILDER_IMPL); 134 } catch (ClassNotFoundException ex) { 135 if ( Util.THIS.isLoggable() ) Util.THIS.debug ("!!! TreeStreamSource.getImplementation", ex); 136 137 return null; 138 } 139 140 try { 141 java.lang.reflect.Constructor impl_const = impl_c.getConstructor (new Class [] { Class .class, InputSource.class, EntityResolver .class, TreeStreamBuilderErrorHandler.class }); 142 return (TreeBuilder) impl_const.newInstance (new Object [] { buildClass, inputSource, getSystemEntityResolver(), errorHolder }); 143 } catch (java.lang.reflect.InvocationTargetException ex) { 145 if ( Util.THIS.isLoggable() ) Util.THIS.debug (ex); 146 147 return null; 148 } catch (NoSuchMethodException ex) { 149 if ( Util.THIS.isLoggable() ) Util.THIS.debug (ex); 150 151 return null; 152 } catch (InstantiationException ex) { 153 if ( Util.THIS.isLoggable() ) Util.THIS.debug (ex); 154 155 return null; 156 } catch (IllegalAccessException ex) { 157 if ( Util.THIS.isLoggable() ) Util.THIS.debug (ex); 158 159 return null; 160 } 161 162 } 163 164 167 private EntityResolver getSystemEntityResolver() { 168 169 if ( Util.THIS.isLoggable() ) Util.THIS.debug ("TreeStreamSource.getSystemEntityResolver:"); 170 171 UserCatalog catalog = UserCatalog.getDefault(); 172 173 if ( Util.THIS.isLoggable() ) Util.THIS.debug (" UserCatalog.getDefault() = " + catalog); 174 175 EntityResolver resolver = (catalog == null ? null : catalog.getEntityResolver()); 176 177 if ( Util.THIS.isLoggable() ) Util.THIS.debug (" EntityResolver = " + resolver); 178 179 if (resolver == null) return null; 180 181 resolver = new EntityResolverWrapper (resolver); 183 184 return resolver; 185 } 186 187 189 190 194 197 private class ErrorHolder implements TreeStreamBuilderErrorHandler { 198 199 public void message (int type, org.xml.sax.SAXParseException e) { 200 201 if ( Util.THIS.isLoggable() ) Util.THIS.debug ("Builder ex", e); 203 } 204 205 } 207 208 212 215 static class EmptyEntityResolver implements EntityResolver { 216 217 public InputSource resolveEntity (String publicId, String systemId) throws SAXException , IOException { 218 return null; 219 } 220 221 } 223 224 233 static class EntityResolverWrapper implements EntityResolver { 234 235 private final EntityResolver res; 236 237 public EntityResolverWrapper(EntityResolver er) { 238 if (er == null) throw new NullPointerException (); 239 res = er; 240 } 241 242 246 public InputSource resolveEntity (final String publicId, final String systemId) throws SAXException , IOException { 247 248 res.resolveEntity(null, "urn:nowhere"); 253 final ErrorManager emgr = ErrorManager.getDefault(); 254 final InputSource MARK = new InputSource("mark"); 256 try { 257 258 final InputSource result[] = new InputSource[] {MARK}; 259 final SAXException sex[] = new SAXException [1]; 260 final IOException ioex[] = new IOException [1]; 261 262 265 Runnable task = new Runnable () { 266 267 public void run() { 268 269 InputSource is = MARK; 270 try { 271 is = res.resolveEntity(publicId, systemId); 272 } catch (IOException _ioex) { 273 ioex[0] = _ioex; 274 } catch (SAXException _sex) { 275 sex[0] = _sex; 276 } finally { 277 synchronized (EntityResolverWrapper.this) { 278 if (is != MARK) result[0] = is; 279 EntityResolverWrapper.this.notify(); 280 } 281 } 282 } 283 }; 284 285 288 Thread thread = new Thread (task, "Timeouted EntityResolver"); thread.setDaemon(true); 290 thread.start(); 291 292 294 synchronized (this) { if (result[0] == MARK) { 296 wait(300); 297 } 298 } 299 300 if (result[0] == MARK) { 301 302 StatusDisplayer.getDefault().setStatusText (Util.THIS.getString("MSG_resolving")); 303 304 synchronized (this) { int timeout = Integer.getInteger("netbeans.xml.resolver.timeout", 5000).intValue(); if (result[0] == MARK) { 307 wait(timeout); } 309 } 310 } 311 312 if (result[0] != MARK) { 313 return result[0]; 314 } else if (sex[0] != null) { 315 throw sex[0]; 316 } else if (ioex[0] != null) { 317 throw ioex[0]; 318 } else { 319 320 322 thread.interrupt(); 323 thread.setPriority(Thread.MIN_PRIORITY); 324 thread.setName("Zombie"); 326 final IOException CANNOT_CONNECT = 327 new IOException ("Resolution timeout \"" + systemId + "\" (" + publicId + ")"); String pattern = Util.THIS.getString("MSG_cannot_connect"); 329 Object [] params = new String [] {publicId, systemId}; 330 String annotation = MessageFormat.format(pattern, params); 331 emgr.annotate(CANNOT_CONNECT, annotation); 332 333 throw CANNOT_CONNECT; 334 } 335 336 } catch (InterruptedException iex) { 337 338 340 final IOException INTERRUPTED = 341 new IOException ("Resolution interrupted \"" + systemId + "\" (" + publicId + ")"); 343 String pattern = Util.THIS.getString("MSG_interrupted"); 344 Object [] params = new String [] {publicId, systemId}; 345 String annotation = MessageFormat.format(pattern, params); 346 emgr.annotate(INTERRUPTED, annotation); 347 348 throw INTERRUPTED; 349 350 } finally { 351 StatusDisplayer.getDefault().setStatusText(""); } 353 354 } 355 356 public String toString() { 357 return super.toString() + Util.THIS.getString ("PROP_wrapping") + res.toString(); 358 } 359 360 } 362 } 363 | Popular Tags |