1 19 20 package org.apache.tools.ant.module.bridge; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.io.File ; 25 import java.io.FilenameFilter ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.PrintStream ; 29 import java.lang.ref.Reference ; 30 import java.lang.ref.SoftReference ; 31 import java.lang.reflect.Method ; 32 import java.net.URL ; 33 import java.net.URLClassLoader ; 34 import java.security.AllPermission ; 35 import java.security.CodeSource ; 36 import java.security.PermissionCollection ; 37 import java.security.Permissions ; 38 import java.util.ArrayList ; 39 import java.util.Arrays ; 40 import java.util.Collection ; 41 import java.util.Collections ; 42 import java.util.Enumeration ; 43 import java.util.HashMap ; 44 import java.util.Iterator ; 45 import java.util.LinkedHashSet ; 46 import java.util.List ; 47 import java.util.Locale ; 48 import java.util.Map ; 49 import javax.swing.event.ChangeEvent ; 50 import javax.swing.event.ChangeListener ; 51 import org.apache.tools.ant.module.AntSettings; 52 import org.openide.ErrorManager; 53 import org.openide.modules.InstalledFileLocator; 54 import org.openide.modules.ModuleInfo; 55 import org.openide.util.Lookup; 56 import org.openide.util.LookupEvent; 57 import org.openide.util.LookupListener; 58 import org.openide.util.io.NullOutputStream; 59 import org.openide.xml.XMLUtil; 60 import org.w3c.dom.Document ; 61 import org.w3c.dom.Element ; 62 import org.w3c.dom.Node ; 63 import org.w3c.dom.NodeList ; 64 import org.xml.sax.InputSource ; 65 import org.xml.sax.SAXException ; 66 67 71 public final class AntBridge { 72 73 private static final ErrorManager err = ErrorManager.getDefault().getInstance(AntBridge.class.getName()); 74 75 private AntBridge() {} 76 77 private static final class AntInstance { 78 public final String mainClassPath; 79 public final ClassLoader mainClassLoader; 80 public final ClassLoader bridgeClassLoader; 81 public final BridgeInterface bridge; 82 public final Map <String ,Map <String ,Class >> customDefs; 83 public final Map <String ,ClassLoader > customDefClassLoaders; 84 public AntInstance(String mainClassPath, ClassLoader mainClassLoader, 85 ClassLoader bridgeClassLoader, BridgeInterface bridge, 86 Map <String ,Map <String ,Class >> customDefs, 87 Map <String ,ClassLoader > customDefClassLoaders) { 88 this.mainClassPath = mainClassPath; 89 this.mainClassLoader = mainClassLoader; 90 this.bridgeClassLoader = bridgeClassLoader; 91 this.bridge = bridge; 92 this.customDefs = customDefs; 93 this.customDefClassLoaders = customDefClassLoaders; 94 } 95 } 96 private static Reference <AntInstance> antInstance = null; 97 98 private static List <ChangeListener > listeners = new ArrayList <ChangeListener >(); 99 100 private static final class MiscListener implements PropertyChangeListener , LookupListener { 101 MiscListener() {} 102 private ModuleInfo[] modules = null; 103 public void propertyChange(PropertyChangeEvent ev) { 104 String prop = ev.getPropertyName(); 105 if (AntSettings.PROP_ANT_HOME.equals(prop) || 106 AntSettings.PROP_EXTRA_CLASSPATH.equals(prop) || 107 AntSettings.PROP_AUTOMATIC_EXTRA_CLASSPATH.equals(prop)) { 108 err.log("AntBridge got settings change in " + prop); 109 fireChange(); 110 } else if (ModuleInfo.PROP_ENABLED.equals(prop)) { 111 err.log("AntBridge got module enablement change on " + ev.getSource()); 112 fireChange(); 113 } 114 } 115 public void resultChanged(LookupEvent ev) { 116 err.log("AntModule got ModuleInfo change"); 117 synchronized (this) { 118 if (modules != null) { 119 for (ModuleInfo module : modules) { 120 module.removePropertyChangeListener(this); 121 } 122 modules = null; 123 } 124 } 125 fireChange(); 126 } 127 public synchronized ModuleInfo[] getEnabledModules() { 128 if (modules == null) { 129 Collection <? extends ModuleInfo> c = modulesResult.allInstances(); 130 modules = c.toArray(new ModuleInfo[c.size()]); 131 for (ModuleInfo module : modules) { 132 module.addPropertyChangeListener(this); 133 } 134 } 135 List <ModuleInfo> enabledModules = new ArrayList <ModuleInfo>(modules.length); 136 for (ModuleInfo module : modules) { 137 if (module.isEnabled()) { 138 enabledModules.add(module); 139 } 140 } 141 return enabledModules.toArray(new ModuleInfo[enabledModules.size()]); 142 } 143 } 144 private static MiscListener miscListener = new MiscListener(); 145 private static Lookup.Result<ModuleInfo> modulesResult = Lookup.getDefault().lookupResult(ModuleInfo.class); 146 static { 147 AntSettings.addPropertyChangeListener(miscListener); 148 modulesResult.addLookupListener(miscListener); 149 } 150 151 155 public static synchronized void addChangeListener(ChangeListener l) { 156 listeners.add(l); 157 } 158 159 162 public static synchronized void removeChangeListener(ChangeListener l) { 163 listeners.remove(l); 164 } 165 166 private static void fireChange() { 167 antInstance = null; 168 ChangeEvent ev = new ChangeEvent (AntBridge.class); 169 ChangeListener [] ls; 170 synchronized (AntBridge.class) { 171 ls = listeners.toArray(new ChangeListener [listeners.size()]); 172 } 173 for (ChangeListener l : ls) { 174 l.stateChanged(ev); 175 } 176 } 177 178 182 public static ClassLoader getMainClassLoader() { 183 return getAntInstance().mainClassLoader; 184 } 185 186 195 public static Map <String ,Map <String ,Class >> getCustomDefsWithNamespace() { 196 return getAntInstance().customDefs; 197 } 198 199 202 public static Map <String ,Map <String ,Class >> getCustomDefsNoNamespace() { 203 Map <String ,Map <String ,Class >> m = new HashMap <String ,Map <String ,Class >>(); 204 for (Map.Entry <String ,Map <String ,Class >> entry : getCustomDefsWithNamespace().entrySet()) { 205 String type = entry.getKey(); 206 Map <String ,Class > defs = entry.getValue(); 207 Map <String ,Class > m2 = new HashMap <String ,Class >(); 208 for (Map.Entry <String ,Class > entry2 : defs.entrySet()) { 209 String fqn = entry2.getKey(); 210 Class clazz = entry2.getValue(); 211 String name; 212 int idx = fqn.lastIndexOf(':'); 213 if (idx != -1) { 214 name = fqn.substring(idx + 1); 215 } else { 216 name = fqn; 217 } 218 m2.put(name, clazz); 219 } 220 m.put(type, m2); 221 } 222 return m; 223 } 224 225 229 public static Map <String ,ClassLoader > getCustomDefClassLoaders() throws IOException { 231 return getAntInstance().customDefClassLoaders; 232 } 233 234 237 public static BridgeInterface getInterface() { 238 return getAntInstance().bridge; 239 } 240 241 private synchronized static AntInstance getAntInstance() { 242 AntInstance ai; 243 if (antInstance != null) { 244 ai = antInstance.get(); 245 } else { 246 ai = null; 247 } 248 if (ai == null) { 249 ai = createAntInstance(); 250 antInstance = new SoftReference <AntInstance>(ai); 254 } 255 return ai; 256 } 257 258 private static AntInstance createAntInstance() { 259 err.log("AntBridge.createAntInstance - loading Ant installation..."); 260 try { 261 List <File > mainClassPath = createMainClassPath(); 262 err.log("mainClassPath=" + mainClassPath); 263 ClassLoader main = createMainClassLoader(mainClassPath); 264 ClassLoader bridgeLoader = createBridgeClassLoader(main); 265 Class ihClazz = Class.forName("org.apache.tools.ant.input.InputHandler", false, bridgeLoader); Class <? extends BridgeInterface> impl = bridgeLoader.loadClass("org.apache.tools.ant.module.bridge.impl.BridgeImpl").asSubclass(BridgeInterface.class); if (AntSettings.getAntHome() != null) { 271 ClassLoader loaderUsedForAnt = ihClazz.getClassLoader(); 272 if (loaderUsedForAnt != main) { 273 throw new IllegalStateException ("Wrong class loader is finding Ant: " + loaderUsedForAnt); } 275 Class ihClazz2 = Class.forName("org.apache.tools.ant.input.InputHandler", false, main); if (ihClazz2 != ihClazz) { 277 throw new IllegalStateException ("Main and bridge class loaders do not agree on version of Ant: " + ihClazz2.getClassLoader()); } 279 try { 280 Class alClazz = Class.forName("org.apache.tools.ant.taskdefs.Antlib", false, bridgeLoader); if (alClazz.getClassLoader() != main) { 282 throw new IllegalStateException ("Bridge loader is loading stuff from elsewhere: " + alClazz.getClassLoader()); } 284 Class alClazz2 = Class.forName("org.apache.tools.ant.taskdefs.Antlib", false, main); if (alClazz2 != alClazz) { 286 throw new IllegalStateException ("Main and bridge class loaders do not agree on version of Ant: " + alClazz2.getClassLoader()); } 288 } catch (ClassNotFoundException cnfe) { 289 } 291 if (impl.getClassLoader() != bridgeLoader) { 292 throw new IllegalStateException ("Wrong class loader is finding bridge impl: " + impl.getClassLoader()); } 294 } Map <String ,ClassLoader > cDCLs = createCustomDefClassLoaders(main); 296 return new AntInstance(classPathToString(mainClassPath), main, bridgeLoader, impl.newInstance(), createCustomDefs(cDCLs), cDCLs); 297 } catch (Exception e) { 298 return fallback(e); 299 } catch (LinkageError e) { 300 return fallback(e); 301 } 302 } 303 304 private static AntInstance fallback(Throwable e) { 305 ClassLoader dummy = ClassLoader.getSystemClassLoader(); 306 Map <String ,Map <String ,Class >> defs = new HashMap <String ,Map <String ,Class >>(); 307 defs.put("task", new HashMap <String ,Class >()); defs.put("type", new HashMap <String ,Class >()); return new AntInstance("", dummy, dummy, new DummyBridgeImpl(e), defs, Collections.<String ,ClassLoader >emptyMap()); 310 } 311 312 private static final class JarFilter implements FilenameFilter { 313 JarFilter() {} 314 public boolean accept(File dir, String name) { 315 return name.toLowerCase(Locale.US).endsWith(".jar"); } 317 } 318 319 private static String classPathToString(List <File > cp) { 320 StringBuffer b = new StringBuffer (); 321 Iterator <File > it = cp.iterator(); 322 while (it.hasNext()) { 323 b.append(it.next().getAbsolutePath()); 324 if (it.hasNext()) { 325 b.append(File.pathSeparator); 326 } 327 } 328 return b.toString(); 329 } 330 331 private static String originalJavaClassPath = System.getProperty("java.class.path"); 337 public static String getMainClassPath() { 338 return getAntInstance().mainClassPath + File.pathSeparatorChar + originalJavaClassPath; 339 } 340 341 private static List <File > createMainClassPath() throws Exception { 342 Collection <File > cp = new LinkedHashSet <File >(); 344 File antHome = AntSettings.getAntHome(); 345 if (antHome != null) { 346 File libdir = new File (antHome, "lib"); if (!libdir.isDirectory()) { 348 throw new IOException ("No such Ant library dir: " + libdir); } 350 err.log("Creating main class loader from " + libdir); 351 File [] patches = new File (libdir.getParentFile(), "patches").listFiles(new JarFilter()); if (patches != null) { 354 cp.addAll(Arrays.asList(patches)); 355 } 356 File [] libs = libdir.listFiles(new JarFilter()); 358 if (libs == null) { 359 throw new IOException ("Listing: " + libdir); } 361 cp.addAll(Arrays.asList(libs)); 362 } else { 363 File toolsJar = new File (new File (new File (System.getProperty("java.home")).getParentFile(), "lib"), "tools.jar"); 365 if (toolsJar.isFile()) { 366 cp.add(toolsJar); 367 } 368 } 369 cp.addAll(AntSettings.getExtraClasspath()); 371 cp.addAll(AntSettings.getAutomaticExtraClasspath()); 372 return new ArrayList <File >(cp); 382 } 383 384 private static ClassLoader createMainClassLoader(List <File > mainClassPath) throws Exception { 385 URL [] cp = new URL [mainClassPath.size()]; 386 Iterator <File > it = mainClassPath.iterator(); 387 int i = 0; 388 while (it.hasNext()) { 389 cp[i++] = it.next().toURI().toURL(); 390 } 391 if (AntSettings.getAntHome() != null) { 392 ClassLoader parent = ClassLoader.getSystemClassLoader(); 393 if (err.isLoggable(ErrorManager.INFORMATIONAL)) { 394 List <URL > parentURLs; 395 if (parent instanceof URLClassLoader ) { 396 parentURLs = Arrays.asList(((URLClassLoader ) parent).getURLs()); 397 } else { 398 parentURLs = null; 399 } 400 err.log("AntBridge.createMainClassLoader: cp=" + Arrays.asList(cp) + " parent.urls=" + parentURLs); 401 } 402 return new MaskedClassLoader(cp, parent); 403 } else { 404 ClassLoader existing = AntBridge.class.getClassLoader(); 406 if (existing instanceof URLClassLoader ) { 407 try { 408 Method addURL = URLClassLoader .class.getDeclaredMethod("addURL", URL .class); 413 addURL.setAccessible(true); 414 for (URL u : cp) { 415 addURL.invoke(existing, u); 416 } 417 return existing; 418 } catch (Exception e) { 419 err.notify(ErrorManager.WARNING, e); 421 } 422 } 423 return new AllPermissionURLClassLoader(cp, existing); 425 } 426 } 427 428 private static ClassLoader createBridgeClassLoader(ClassLoader main) throws Exception { 429 File bridgeJar = InstalledFileLocator.getDefault().locate("ant/nblib/bridge.jar", "org.apache.tools.ant.module", false); if (bridgeJar == null) { 431 return main; 433 } 434 return createAuxClassLoader(bridgeJar, main, AntBridge.class.getClassLoader()); 435 } 436 437 private static ClassLoader createAuxClassLoader(File lib, ClassLoader main, ClassLoader moduleLoader) throws IOException { 438 return new AuxClassLoader(moduleLoader, main, lib.toURI().toURL()); 439 } 440 441 445 private static Map <String ,ClassLoader > createCustomDefClassLoaders(ClassLoader main) throws IOException { 446 Map <String ,ClassLoader > m = new HashMap <String ,ClassLoader >(); 447 ModuleInfo[] modules = miscListener.getEnabledModules(); 448 InstalledFileLocator ifl = InstalledFileLocator.getDefault(); 449 for (ModuleInfo module : modules) { 450 String cnb = module.getCodeNameBase(); 451 String cnbDashes = cnb.replace('.', '-'); 452 File lib = ifl.locate("ant/nblib/" + cnbDashes + ".jar", cnb, false); if (lib == null) { 454 if (main.getResource(cnb.replace('.', '/') + "/antlib.xml") != null) { m.put(cnb, main); 457 } 458 continue; 459 } 460 ClassLoader l = createAuxClassLoader(lib, main, module.getClassLoader()); 461 m.put(cnb, l); 462 } 463 return m; 464 } 465 466 private static Map <String ,Map <String ,Class >> createCustomDefs(Map <String ,ClassLoader > cDCLs) throws IOException { 467 Map <String ,Map <String ,Class >> m = new HashMap <String ,Map <String ,Class >>(); 468 Map <String ,Class > tasks = new HashMap <String ,Class >(); 469 Map <String ,Class > types = new HashMap <String ,Class >(); 470 m.put("task", tasks); m.put("type", types); for (Map.Entry <String ,ClassLoader > entry : cDCLs.entrySet()) { 474 String cnb = entry.getKey(); 475 ClassLoader l = entry.getValue(); 476 String resource = cnb.replace('.', '/') + "/antlib.xml"; URL antlib = l.getResource(resource); 478 if (antlib == null) { 479 throw new IOException ("Could not find " + resource + " in ant/nblib/" + cnb.replace('.', '-') + ".jar"); } 481 Document doc; 482 try { 483 doc = XMLUtil.parse(new InputSource (antlib.toExternalForm()), false, true, null, null); 484 } catch (SAXException e) { 485 throw (IOException )new IOException (e.toString()).initCause(e); 486 } 487 Element docEl = doc.getDocumentElement(); 488 if (!docEl.getLocalName().equals("antlib")) { throw new IOException ("Bad root element for " + antlib + ": " + docEl); } 491 NodeList nl = docEl.getChildNodes(); 492 Map <String ,String > newTaskDefs = new HashMap <String ,String >(); 493 Map <String ,String > newTypeDefs = new HashMap <String ,String >(); 494 for (int i = 0; i < nl.getLength(); i++) { 495 Node n = nl.item(i); 496 if (n.getNodeType() != Node.ELEMENT_NODE) { 497 continue; 498 } 499 Element def = (Element )n; 500 boolean type; 501 if (def.getNodeName().equals("taskdef")) { type = false; 503 } else if (def.getNodeName().equals("typedef")) { type = true; 505 } else { 506 err.log(ErrorManager.WARNING, "Warning: unrecognized definition " + def + " in " + antlib); 507 continue; 508 } 509 String name = def.getAttribute("name"); if (name == null) { 511 err.log(ErrorManager.WARNING, "Warning: skipping definition " + def + " with no 'name' in " + antlib); 514 continue; 515 } 516 String classname = def.getAttribute("classname"); if (classname == null) { 518 throw new IOException ("No 'classname' attr on def of " + name + " in " + antlib); } 521 String nsname = "antlib:" + cnb + ":" + name; (type ? newTypeDefs : newTaskDefs).put(nsname, classname); 524 } 525 loadDefs(newTaskDefs, tasks, l); 526 loadDefs(newTypeDefs, types, l); 527 } 528 return m; 529 } 530 531 private static void loadDefs(Map <String ,String > p, Map <String ,Class > defs, ClassLoader l) throws IOException { 532 for (Map.Entry <String ,String > entry : p.entrySet()) { 534 String name = entry.getKey(); 535 String clazzname = entry.getValue(); 536 try { 537 Class clazz = l.loadClass(clazzname); 538 defs.put(name, clazz); 539 } catch (ClassNotFoundException cnfe) { 540 throw (IOException ) new IOException ("Could not load class " + clazzname + ": " + cnfe).initCause(cnfe); } catch (NoClassDefFoundError ncdfe) { 543 err.log("AntBridge.loadDefs: skipping " + clazzname + ": " + ncdfe); 546 } catch (LinkageError e) { 547 throw (IOException ) new IOException ("Could not load class " + clazzname + ": " + e).initCause(e); } 550 } 551 } 552 553 static class AllPermissionURLClassLoader extends URLClassLoader { 554 555 private static PermissionCollection allPermission; 556 private static synchronized PermissionCollection getAllPermissions() { 557 if (allPermission == null) { 558 allPermission = new Permissions (); 559 allPermission.add(new AllPermission ()); 560 } 561 return allPermission; 562 } 563 564 public AllPermissionURLClassLoader(URL [] urls, ClassLoader parent) { 565 super(urls, parent); 566 } 567 568 @Override  569 protected final PermissionCollection getPermissions(CodeSource cs) { 570 return getAllPermissions(); 571 } 572 573 @Override  574 public String toString() { 575 return super.toString() + "[parent=" + getParent() + ",urls=" + Arrays.asList(getURLs()) + "]"; 576 } 577 578 @Override  579 public URL getResource(String name) { 580 URL u = super.getResource(name); 581 if (err.isLoggable(ErrorManager.INFORMATIONAL)) { 582 err.log("APURLCL.gR: " + name + " -> " + u + " [" + this + "]"); 583 } 584 return u; 585 } 586 587 @Override  588 public Enumeration <URL > findResources(String name) throws IOException { 589 try { 590 Enumeration <URL > us = super.findResources(name); 591 if (err.isLoggable(ErrorManager.INFORMATIONAL)) { 592 List <URL > resources = Collections.list(us); 594 us = Collections.enumeration(resources); 595 err.log("APURLCL.fRs: " + name + " -> " + resources + " [" + this + "]"); 596 } 597 return us; 598 } catch (IOException e) { 599 if (err.isLoggable(ErrorManager.INFORMATIONAL)) { 600 err.notify(ErrorManager.INFORMATIONAL, e); 601 } 602 throw e; 603 } 604 } 605 606 619 620 } 621 622 private static boolean masked(String clazz) { 623 return clazz.startsWith("org.apache.tools.") || 624 clazz.startsWith("org.netbeans.") || 625 clazz.startsWith("org.openide.") || 626 clazz.startsWith("org.openidex."); } 628 629 633 private static final class MaskedClassLoader extends AllPermissionURLClassLoader { 634 635 public MaskedClassLoader(URL [] urls, ClassLoader parent) { 636 super(urls, parent); 637 } 638 639 @Override  640 protected synchronized Class <?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 641 if (masked(name)) { 642 Class c = findLoadedClass(name); 643 if (c == null) { 645 c = findClass(name); 646 } 647 if (resolve) { 648 resolveClass(c); 649 } 650 return c; 651 } else { 652 return super.loadClass(name, resolve); 653 } 654 } 655 656 } 657 658 666 private static int delegating = 0; 667 private static InputStream origIn; 668 private static PrintStream origOut, origErr; 669 private static Map <ThreadGroup ,InputStream > delegateIns = new HashMap <ThreadGroup ,InputStream >(); 670 private static Map <ThreadGroup ,PrintStream > delegateOuts = new HashMap <ThreadGroup ,PrintStream >(); 671 private static Map <ThreadGroup ,PrintStream > delegateErrs = new HashMap <ThreadGroup ,PrintStream >(); 672 673 private static List <Thread > suspendedDelegationTasks = new ArrayList <Thread >(); 674 675 683 public static synchronized void pushSystemInOutErr(InputStream in, PrintStream out, PrintStream err) { 684 if (delegating++ == 0) { 685 origIn = System.in; 686 origOut = System.out; 687 origErr = System.err; 688 System.setIn(new MultiplexInputStream()); 689 System.setOut(new MultiplexPrintStream(false)); 690 System.setErr(new MultiplexPrintStream(true)); 691 } 692 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 693 delegateIns.put(tg, in); 694 delegateOuts.put(tg, out); 695 delegateErrs.put(tg, err); 696 } 697 698 701 public static synchronized void restoreSystemInOutErr() { 702 assert delegating > 0; 703 if (--delegating == 0) { 704 System.setIn(origIn); 705 System.setOut(origOut); 706 System.setErr(origErr); 707 origIn = null; 708 origOut = null; 709 origErr = null; 710 } 711 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 712 delegateIns.remove(tg); 713 delegateOuts.remove(tg); 714 delegateErrs.remove(tg); 715 } 716 717 724 public static synchronized void suspendDelegation() { 725 Thread t = Thread.currentThread(); 726 suspendedDelegationTasks.add(t); 730 } 731 732 736 public static synchronized void resumeDelegation() { 737 Thread t = Thread.currentThread(); 738 assert suspendedDelegationTasks.contains(t) : "Have not suspended delegation in " + t; 741 suspendedDelegationTasks.remove(t); 742 } 743 744 private static final class MultiplexInputStream extends InputStream { 745 746 public MultiplexInputStream() {} 747 748 private InputStream delegate() { 749 Thread t = Thread.currentThread(); 750 ThreadGroup tg = t.getThreadGroup(); 751 while (tg != null && !delegateIns.containsKey(tg)) { 752 tg = tg.getParent(); 753 } 754 InputStream is = delegateIns.get(tg); 755 if (is != null && !suspendedDelegationTasks.contains(t)) { 756 return is; 757 } else if (delegating > 0) { 758 assert origIn != null; 759 return origIn; 760 } else { 761 return System.in; 763 } 764 } 765 766 @Override  767 public int read() throws IOException { 768 return delegate().read(); 769 } 770 771 @Override  772 public int read(byte[] b) throws IOException { 773 return delegate().read(b); 774 } 775 776 @Override  777 public int read(byte[] b, int off, int len) throws IOException { 778 return delegate().read(b, off, len); 779 } 780 781 @Override  782 public int available() throws IOException { 783 return delegate().available(); 784 } 785 786 @Override  787 public boolean markSupported() { 788 return delegate().markSupported(); 789 } 790 791 @Override  792 public void mark(int readlimit) { 793 delegate().mark(readlimit); 794 } 795 796 @Override  797 public void close() throws IOException { 798 delegate().close(); 799 } 800 801 @Override  802 public long skip(long n) throws IOException { 803 return delegate().skip(n); 804 } 805 806 @Override  807 public void reset() throws IOException { 808 delegate().reset(); 809 } 810 811 } 812 813 private static final class MultiplexPrintStream extends PrintStream { 814 815 private final boolean err; 816 817 public MultiplexPrintStream(boolean err) { 818 this(new NullOutputStream(), err); 819 } 820 821 private MultiplexPrintStream(NullOutputStream nos, boolean err) { 822 super(nos); 823 nos.throwException = true; 824 this.err = err; 825 } 826 827 private PrintStream delegate() { 828 Thread t = Thread.currentThread(); 829 ThreadGroup tg = t.getThreadGroup(); 830 Map <ThreadGroup ,PrintStream > delegates = err ? delegateErrs : delegateOuts; 831 while (tg != null && !delegates.containsKey(tg)) { 832 tg = tg.getParent(); 833 } 834 PrintStream ps = delegates.get(tg); 835 if (ps != null && !suspendedDelegationTasks.contains(t)) { 836 assert !(ps instanceof MultiplexPrintStream); 837 return ps; 838 } else if (delegating > 0) { 839 PrintStream orig = err ? origErr : origOut; 840 assert orig != null; 841 assert !(orig instanceof MultiplexPrintStream); 842 return orig; 843 } else { 844 PrintStream stream = err ? System.err : System.out; 846 assert !(stream instanceof MultiplexPrintStream); return stream; 848 } 849 } 850 851 @Override  852 public boolean checkError() { 853 return delegate().checkError(); 854 } 855 856 @Override  857 public void close() { 858 delegate().close(); 859 } 860 861 @Override  862 public void flush() { 863 delegate().flush(); 864 } 865 866 @Override  867 public void print(long l) { 868 delegate().print(l); 869 } 870 871 @Override  872 public void print(char[] s) { 873 delegate().print(s); 874 } 875 876 @Override  877 public void print(int i) { 878 delegate().print(i); 879 } 880 881 @Override  882 public void print(boolean b) { 883 delegate().print(b); 884 } 885 886 @Override  887 public void print(char c) { 888 delegate().print(c); 889 } 890 891 @Override  892 public void print(float f) { 893 delegate().print(f); 894 } 895 896 @Override  897 public void print(double d) { 898 delegate().print(d); 899 } 900 901 @Override  902 public void print(Object obj) { 903 delegate().print(obj); 904 } 905 906 @Override  907 public void print(String s) { 908 delegate().print(s); 909 } 910 911 @Override  912 public void println(double x) { 913 delegate().println(x); 914 } 915 916 @Override  917 public void println(Object x) { 918 delegate().println(x); 919 } 920 921 @Override  922 public void println(float x) { 923 delegate().println(x); 924 } 925 926 @Override  927 public void println(int x) { 928 delegate().println(x); 929 } 930 931 @Override  932 public void println(char x) { 933 delegate().println(x); 934 } 935 936 @Override  937 public void println(boolean x) { 938 delegate().println(x); 939 } 940 941 @Override  942 public void println(String x) { 943 delegate().println(x); 944 } 945 946 @Override  947 public void println(char[] x) { 948 delegate().println(x); 949 } 950 951 @Override  952 public void println() { 953 delegate().println(); 954 } 955 956 @Override  957 public void println(long x) { 958 delegate().println(x); 959 } 960 961 @Override  962 public void write(int b) { 963 delegate().write(b); 964 } 965 966 @Override  967 public void write(byte[] b) throws IOException { 968 delegate().write(b); 969 } 970 971 @Override  972 public void write(byte[] b, int off, int len) { 973 delegate().write(b, off, len); 974 } 975 976 980 } 981 982 985 private static int fakingJavaClassPath = 0; 986 987 992 public static synchronized void fakeJavaClassPath() { 993 if (fakingJavaClassPath++ == 0) { 994 String cp = getMainClassPath(); 995 err.log("Faking java.class.path=" + cp); 996 System.setProperty("java.class.path", cp); } 998 } 999 1000 1003 public static synchronized void unfakeJavaClassPath() { 1004 if (--fakingJavaClassPath == 0) { 1005 err.log("Restoring java.class.path=" + originalJavaClassPath); 1006 System.setProperty("java.class.path", originalJavaClassPath); } 1008 } 1009 1010} 1011 | Popular Tags |