1 16 package com.google.gwt.dev; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 import com.google.gwt.core.ext.UnableToCompleteException; 20 import com.google.gwt.core.ext.TreeLogger.Type; 21 import com.google.gwt.core.ext.typeinfo.JClassType; 22 import com.google.gwt.core.ext.typeinfo.TypeOracle; 23 import com.google.gwt.dev.cfg.Compilation; 24 import com.google.gwt.dev.cfg.CompilationSchema; 25 import com.google.gwt.dev.cfg.Compilations; 26 import com.google.gwt.dev.cfg.ModuleDef; 27 import com.google.gwt.dev.cfg.ModuleDefLoader; 28 import com.google.gwt.dev.cfg.Properties; 29 import com.google.gwt.dev.cfg.Property; 30 import com.google.gwt.dev.cfg.PropertyPermutations; 31 import com.google.gwt.dev.cfg.Rules; 32 import com.google.gwt.dev.cfg.StaticPropertyOracle; 33 import com.google.gwt.dev.jdt.CacheManager; 34 import com.google.gwt.dev.jdt.RebindPermutationOracle; 35 import com.google.gwt.dev.jdt.StandardSourceOracle; 36 import com.google.gwt.dev.jdt.WebModeCompilerFrontEnd; 37 import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler; 38 import com.google.gwt.dev.shell.StandardRebindOracle; 39 import com.google.gwt.dev.util.DefaultTextOutput; 40 import com.google.gwt.dev.util.SelectionScriptGenerator; 41 import com.google.gwt.dev.util.Util; 42 import com.google.gwt.dev.util.arg.ArgHandlerGenDir; 43 import com.google.gwt.dev.util.arg.ArgHandlerLogLevel; 44 import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle; 45 import com.google.gwt.dev.util.arg.ArgHandlerTreeLoggerFlag; 46 import com.google.gwt.dev.util.log.AbstractTreeLogger; 47 import com.google.gwt.dev.util.log.DetachedTreeLoggerWindow; 48 import com.google.gwt.dev.util.log.PrintWriterTreeLogger; 49 import com.google.gwt.dev.util.xml.ReflectiveParser; 50 import com.google.gwt.util.tools.ArgHandlerExtra; 51 import com.google.gwt.util.tools.ArgHandlerOutDir; 52 import com.google.gwt.util.tools.ToolBase; 53 import com.google.gwt.util.tools.Utility; 54 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 58 import java.io.File ; 59 import java.io.FileNotFoundException ; 60 import java.io.FileReader ; 61 import java.io.FilenameFilter ; 62 import java.io.UnsupportedEncodingException ; 63 import java.net.URL ; 64 import java.util.ArrayList ; 65 import java.util.HashMap ; 66 import java.util.HashSet ; 67 import java.util.Iterator ; 68 import java.util.List ; 69 import java.util.Map ; 70 import java.util.Set ; 71 72 import javax.xml.parsers.DocumentBuilder ; 73 import javax.xml.parsers.DocumentBuilderFactory ; 74 import javax.xml.parsers.ParserConfigurationException ; 75 76 79 public class GWTCompiler extends ToolBase { 80 81 private class ArgHandlerModuleName extends ArgHandlerExtra { 82 83 public boolean addExtraArg(String arg) { 84 setModuleName(arg); 85 return true; 86 } 87 88 public String getPurpose() { 89 return "Specifies the name of the module to compile"; 90 } 91 92 public String [] getTagArgs() { 93 return new String [] {"module"}; 94 } 95 96 public boolean isRequired() { 97 return true; 98 } 99 } 100 101 106 private class CompilationRebindOracle extends StandardRebindOracle { 107 108 private final Map cache = new HashMap (); 109 110 private Compilation compilation; 111 112 public CompilationRebindOracle() { 113 super(typeOracle, propOracle, rules, genDir, outDir, cacheManager); 114 } 115 116 121 public String rebind(TreeLogger logger, String in) 122 throws UnableToCompleteException { 123 String out = (String ) cache.get(in); 124 if (out == null) { 125 out = super.rebind(logger, in); 128 cache.put(in, out); 129 } else { 130 String msg = "Rebind answer for '" + in + "' found in cache " + out; 133 logger.log(TreeLogger.DEBUG, msg, null); 134 } 135 136 if (compilation != null && compilation.recordDecision(in, out)) { 137 List genTypes = (List ) generatedTypesByResultTypeName.get(out); 138 if (genTypes != null) { 139 for (Iterator iter = genTypes.iterator(); iter.hasNext();) { 140 JClassType genType = (JClassType) iter.next(); 141 String sourceHash = genType.getTypeHash(); 142 String genTypeName = genType.getQualifiedSourceName(); 143 compilation.recordGeneratedTypeHash(genTypeName, sourceHash); 144 } 145 } 146 } 147 148 return out; 149 } 150 151 public void recordInto(Compilation compilation) { 152 this.compilation = compilation; 153 } 154 } 155 156 private class DistillerRebindPermutationOracle implements 157 RebindPermutationOracle { 158 159 private final StandardRebindOracle rebindOracle = new StandardRebindOracle( 160 typeOracle, propOracle, rules, genDir, outDir, cacheManager) { 161 162 165 protected void onGeneratedTypes(String result, JClassType[] genTypes) { 166 List list = new ArrayList (); 167 Util.addAll(list, genTypes); 168 Object existing = generatedTypesByResultTypeName.put(result, list); 169 assert (existing == null) : "Internal error: redundant notification of generated types"; 170 } 171 }; 172 173 public String [] getAllPossibleRebindAnswers(TreeLogger logger, 174 String requestTypeName) throws UnableToCompleteException { 175 176 String msg = "Computing all possible rebind results for '" 177 + requestTypeName + "'"; 178 logger = logger.branch(TreeLogger.DEBUG, msg, null); 179 180 Set answers = new HashSet (); 181 182 Property[] orderedProps = perms.getOrderedProperties(); 183 for (Iterator iter = perms.iterator(); iter.hasNext();) { 184 String [] orderedPropValues = (String []) iter.next(); 185 186 propOracle.setPropertyValues(orderedProps, orderedPropValues); 192 193 logProperties(logger, orderedProps, orderedPropValues); 195 String resultTypeName = rebindOracle.rebind(logger, requestTypeName); 196 answers.add(resultTypeName); 197 } 198 return (String []) Util.toArray(String .class, answers); 199 } 200 } 201 202 private static final String EXT_CACHE_XML = ".cache.xml"; 203 204 public static void main(String [] args) { 205 211 GWTCompiler compiler = new GWTCompiler(); 212 if (compiler.processArgs(args)) { 213 if (compiler.run()) { 214 System.exit(0); 216 } 217 } 218 System.exit(1); 220 } 221 222 private final CacheManager cacheManager; 223 224 private Compilations compilations = new Compilations(); 225 226 private String [] declEntryPts; 227 228 private File genDir; 229 230 private Map generatedTypesByResultTypeName = new HashMap (); 231 232 private JavaToJavaScriptCompiler jjs; 233 234 private Type logLevel; 235 236 private ModuleDef module; 237 238 private String moduleName; 239 240 private boolean obfuscate; 241 242 private File outDir; 243 244 private PropertyPermutations perms; 245 246 private boolean prettyNames; 247 248 private Properties properties; 249 250 private StaticPropertyOracle propOracle = new StaticPropertyOracle(); 251 252 private RebindPermutationOracle rebindPermOracle; 253 254 private Rules rules; 255 256 private StandardSourceOracle sourceOracle; 257 258 private TypeOracle typeOracle; 259 260 private boolean useGuiLogger; 261 262 public GWTCompiler() { 263 this(null); 264 } 265 266 public GWTCompiler(CacheManager cacheManager) { 267 registerHandler(new ArgHandlerLogLevel() { 268 public void setLogLevel(Type level) { 269 logLevel = level; 270 } 271 }); 272 273 registerHandler(new ArgHandlerGenDir() { 274 public void setDir(File dir) { 275 genDir = dir; 276 } 277 }); 278 279 registerHandler(new ArgHandlerOutDir() { 280 public void setDir(File dir) { 281 outDir = dir; 282 } 283 }); 284 285 registerHandler(new ArgHandlerTreeLoggerFlag() { 286 public boolean setFlag() { 287 useGuiLogger = true; 288 return true; 289 } 290 }); 291 292 registerHandler(new ArgHandlerModuleName()); 293 294 registerHandler(new ArgHandlerScriptStyle() { 295 public void setStyleDetailed() { 296 GWTCompiler.this.setStyleDetailed(); 297 } 298 299 public void setStyleObfuscated() { 300 GWTCompiler.this.setStyleObfuscated(); 301 } 302 303 public void setStylePretty() { 304 GWTCompiler.this.setStylePretty(); 305 } 306 }); 307 this.cacheManager = cacheManager; 308 } 309 310 public void distill(TreeLogger logger, ModuleDef moduleDef) 311 throws UnableToCompleteException { 312 this.module = moduleDef; 313 314 checkModule(logger); 316 317 outDir = new File (outDir, module.getName()); 319 320 rules = module.getRules(); 321 typeOracle = module.getTypeOracle(logger); 322 sourceOracle = new StandardSourceOracle(typeOracle); 323 declEntryPts = module.getEntryPointTypeNames(); 324 rebindPermOracle = new DistillerRebindPermutationOracle(); 325 properties = module.getProperties(); 326 perms = new PropertyPermutations(properties); 327 WebModeCompilerFrontEnd frontEnd = new WebModeCompilerFrontEnd( 328 sourceOracle, rebindPermOracle); 329 jjs = new JavaToJavaScriptCompiler(logger, frontEnd, declEntryPts, 330 obfuscate, prettyNames); 331 initCompilations(logger); 332 333 SelectionScriptGenerator selGen = compilePermutations(logger); 336 337 writeSelectionScripts(logger, selGen); 340 341 copyPublicFiles(logger); 344 345 logger.log(TreeLogger.INFO, "Compilation succeeded", null); 346 } 347 348 public File getGenDir() { 349 return genDir; 350 } 351 352 public Type getLogLevel() { 353 return logLevel; 354 } 355 356 public String getModuleName() { 357 return moduleName; 358 } 359 360 public boolean getUseGuiLogger() { 361 return useGuiLogger; 362 } 363 364 public void setGenDir(File dir) { 365 genDir = dir; 366 } 367 368 public void setLogLevel(Type level) { 369 this.logLevel = level; 370 } 371 372 public void setModuleName(String name) { 373 moduleName = name; 374 } 375 376 public void setOutDir(File outDir) { 377 this.outDir = outDir; 378 } 379 380 public void setStyleDetailed() { 381 obfuscate = false; 382 prettyNames = false; 383 } 384 385 public void setStyleObfuscated() { 386 obfuscate = true; 387 } 388 389 public void setStylePretty() { 390 obfuscate = false; 391 prettyNames = true; 392 } 393 394 private void checkModule(TreeLogger logger) throws UnableToCompleteException { 395 if (module.getEntryPointTypeNames().length == 0) { 396 logger.log(TreeLogger.ERROR, "Module has no entry points defined", null); 397 throw new UnableToCompleteException(); 398 } 399 } 400 401 private SelectionScriptGenerator compilePermutations(TreeLogger logger) 402 throws UnableToCompleteException { 403 logger = logger.branch(TreeLogger.INFO, "Output will be written into " 404 + outDir, null); 405 Property[] orderedProps = perms.getOrderedProperties(); 406 SelectionScriptGenerator selGen = new SelectionScriptGenerator(module, 407 orderedProps); 408 int permNumber = 1; 409 for (Iterator iter = perms.iterator(); iter.hasNext(); ++permNumber) { 410 String [] orderedPropValues = (String []) iter.next(); 411 String strongName = realizePermutation(logger, orderedProps, 412 orderedPropValues, permNumber); 413 selGen.recordSelection(orderedPropValues, strongName); 414 } 415 return selGen; 416 } 417 418 private void copyPublicFiles(TreeLogger logger) 419 throws UnableToCompleteException { 420 TreeLogger branch = null; 421 boolean anyCopied = false; 422 String [] files = module.getAllPublicFiles(); 423 for (int i = 0; i < files.length; ++i) { 424 URL from = module.findPublicFile(files[i]); 425 File to = new File (outDir, files[i]); 426 boolean copied = Util.copy(logger, from, to); 427 if (copied) { 428 if (!anyCopied) { 429 branch = logger.branch(TreeLogger.INFO, 430 "Copying all files found on public path", null); 431 if (!logger.isLoggable(TreeLogger.TRACE)) { 432 branch = null; 433 } 434 anyCopied = true; 435 } 436 437 if (branch != null) { 438 branch.log(TreeLogger.TRACE, to.getAbsolutePath(), null); 439 } 440 } 441 } 442 } 443 444 private String getHtmlPrefix() { 445 DefaultTextOutput out = new DefaultTextOutput(obfuscate); 446 out.print("<html>"); 447 out.newlineOpt(); 448 449 out.print("<head><script>"); 452 out.newlineOpt(); 453 out.print("var $wnd = parent;"); 454 out.newlineOpt(); 455 out.print("var $doc = $wnd.document;"); 456 out.newlineOpt(); 457 out.print("var $moduleName, $moduleBase;"); 458 out.newlineOpt(); 459 out.print("</script></head>"); 460 out.newlineOpt(); 461 out.print("<body>"); 462 out.newlineOpt(); 463 464 out.print("<font face='arial' size='-1'>This script is part of module</font>"); 467 out.newlineOpt(); 468 out.print("<code>"); 469 out.print(module.getName()); 470 out.print("</code>"); 471 out.newlineOpt(); 472 473 out.print("<script><!--"); 476 out.newline(); 477 return out.toString(); 478 } 479 480 private String getHtmlSuffix() { 481 DefaultTextOutput out = new DefaultTextOutput(obfuscate); 482 String moduleFunction = module.getName().replace('.', '_'); 483 484 out.newlineOpt(); 486 out.print("if ($wnd." + moduleFunction + ") $wnd." + moduleFunction 487 + ".onScriptLoad();"); 488 out.newline(); 489 out.print("--></script></body></html>"); 490 out.newlineOpt(); 491 492 return out.toString(); 493 } 494 495 private String getJsPrefix() { 496 DefaultTextOutput out = new DefaultTextOutput(obfuscate); 497 498 out.print("(function(){"); 499 out.newlineOpt(); 500 501 out.print("var $wnd = window;"); 504 out.newlineOpt(); 505 out.print("var $doc = $wnd.document;"); 506 out.newlineOpt(); 507 out.print("var $moduleName, $moduleBase;"); 508 out.newlineOpt(); 509 510 return out.toString(); 511 } 512 513 private String getJsSuffix() { 514 DefaultTextOutput out = new DefaultTextOutput(obfuscate); 515 String moduleFunction = module.getName().replace('.', '_'); 516 517 out.newlineOpt(); 519 out.print("if (" + moduleFunction + ") {"); 520 out.newlineOpt(); 521 out.print(" var __gwt_initHandlers = " + moduleFunction 522 + ".__gwt_initHandlers;"); 523 out.print(" " + moduleFunction + ".onScriptLoad(gwtOnLoad);"); 524 out.newlineOpt(); 525 out.print("}"); 526 out.newlineOpt(); 527 out.print("})();"); 528 out.newlineOpt(); 529 530 return out.toString(); 531 } 532 533 537 private void initCompilations(TreeLogger logger) 538 throws UnableToCompleteException { 539 File [] cacheXmls = outDir.listFiles(new FilenameFilter () { 540 public boolean accept(File dir, String name) { 541 return name.endsWith(EXT_CACHE_XML); 542 } 543 }); 544 545 if (cacheXmls == null) { 546 return; 547 } 548 549 long newestCup = jjs.getLastModifiedTimeOfNewestCompilationUnit(); 550 for (int i = 0; i < cacheXmls.length; i++) { 551 File cacheXml = cacheXmls[i]; 552 String fn = cacheXml.getName(); 553 String strongName = fn.substring(0, fn.length() - EXT_CACHE_XML.length()); 554 555 long cacheXmlLastMod = cacheXml.lastModified(); 558 if (cacheXmlLastMod < newestCup) { 559 String msg = "Compilation '" + fn 562 + "' is out of date and will be removed"; 563 logger.log(TreeLogger.TRACE, msg, null); 564 Util.deleteFilesStartingWith(outDir, strongName); 565 continue; 566 } 567 568 TreeLogger branch = logger.branch(TreeLogger.DEBUG, 573 "Loading cached compilation: " + cacheXml, null); 574 Compilation c = new Compilation(); 575 c.setStrongName(strongName); 576 CompilationSchema schema = new CompilationSchema(c); 577 FileReader r = null; 578 Throwable caught = null; 579 try { 580 r = new FileReader (cacheXml); 581 ReflectiveParser.parse(logger, schema, r); 582 } catch (FileNotFoundException e) { 583 caught = e; 584 } catch (UnableToCompleteException e) { 585 caught = e; 586 } finally { 587 Utility.close(r); 588 } 589 590 if (caught != null) { 591 String msg = "Unable to load the cached file"; 592 branch.log(TreeLogger.WARN, msg, caught); 593 continue; 594 } 595 596 boolean isBadCompilation = false; 600 String [] genTypes = c.getGeneratedTypeNames(); 601 for (int j = 0; j < genTypes.length; j++) { 602 String genTypeName = genTypes[j]; 603 String cachedHash = c.getTypeHash(genTypeName); 604 JClassType genType = typeOracle.findType(genTypeName); 605 if (genType == null) { 606 String msg = "Compilation '" + fn + "' refers to generated type '" 610 + genTypeName 611 + "' which no longer exists; cache entry will be removed"; 612 branch.log(TreeLogger.TRACE, msg, null); 613 Util.deleteFilesStartingWith(outDir, strongName); 614 isBadCompilation = true; 615 break; 616 } 617 618 String currentHash = genType.getTypeHash(); 619 620 if (!cachedHash.equals(currentHash)) { 621 String msg = "Compilation '" 622 + fn 623 + "' was compiled with a different version of generated source for '" 624 + genTypeName + "'; cache entry will be removed"; 625 branch.log(TreeLogger.TRACE, msg, null); 626 Util.deleteFilesStartingWith(outDir, strongName); 627 isBadCompilation = true; 628 break; 629 } 630 } 631 632 if (!isBadCompilation) { 633 compilations.add(c); 635 } 636 } 637 } 638 639 private void logProperties(TreeLogger logger, Property[] props, 640 String [] values) { 641 if (logger.isLoggable(TreeLogger.DEBUG)) { 642 logger = logger.branch(TreeLogger.DEBUG, "Setting properties", null); 643 for (int i = 0; i < props.length; i++) { 644 String name = props[i].getName(); 645 String value = values[i]; 646 logger.log(TreeLogger.TRACE, name + " = " + value, null); 647 } 648 } 649 } 650 651 660 private String realizePermutation(TreeLogger logger, Property[] currentProps, 661 String [] currentValues, int permNumber) throws UnableToCompleteException { 662 String msg = "Analyzing permutation #" + permNumber; 663 logger = logger.branch(TreeLogger.TRACE, msg, null); 664 665 logProperties(logger, currentProps, currentValues); 666 667 CompilationRebindOracle rebindOracle = new CompilationRebindOracle(); 671 672 propOracle.setPropertyValues(currentProps, currentValues); 677 678 String [] entryPts = module.getEntryPointTypeNames(); 682 Compilation cached = compilations.find(logger, rebindOracle, entryPts); 683 if (cached != null) { 684 msg = "Matches existing compilation " + cached.getStrongName(); 685 logger.log(TreeLogger.TRACE, msg, null); 686 return cached.getStrongName(); 687 } 688 689 Compilation compilation = new Compilation(); 693 rebindOracle.recordInto(compilation); 694 695 String js = jjs.compile(logger, rebindOracle); 698 699 String strongName = writeHtmlAndJsWithStrongName(logger, js); 702 703 compilation.setStrongName(strongName); 706 writeCacheFile(logger, compilation); 707 708 compilations.add(compilation); 711 return compilation.getStrongName(); 712 } 713 714 721 private boolean run() { 722 BootStrapPlatform.setSystemProperties(); 724 725 if (useGuiLogger) { 726 DetachedTreeLoggerWindow loggerWindow = DetachedTreeLoggerWindow.getInstance( 728 "Build Output for " + moduleName, 800, 600, true); 729 730 BootStrapPlatform.maybeInitializeAWT(); 732 733 final AbstractTreeLogger logger = loggerWindow.getLogger(); 734 final boolean[] success = new boolean[1]; 735 736 Thread compilerThread = new Thread (new Runnable () { 739 public void run() { 740 success[0] = GWTCompiler.this.run(logger); 741 } 742 }); 743 744 compilerThread.setName("GWTCompiler Thread"); 745 compilerThread.start(); 746 loggerWindow.run(); 747 748 waitForThreadToTerminate(compilerThread); 751 752 return success[0]; 753 } else { 754 return run(new PrintWriterTreeLogger()); 755 } 756 } 757 758 private boolean run(AbstractTreeLogger logger) { 759 try { 760 logger.setMaxDetail(logLevel); 761 762 ModuleDef moduleDef = ModuleDefLoader.loadFromClassPath(logger, 763 moduleName); 764 distill(logger, moduleDef); 765 return true; 766 } catch (UnableToCompleteException e) { 767 logger.log(TreeLogger.ERROR, "Build failed", null); 770 return false; 771 } 772 } 773 774 781 private void waitForThreadToTerminate(final Thread godot) { 782 boolean isInterrupted = false; 785 try { 786 while (true) { 787 try { 788 godot.join(); 789 return; 790 } catch (InterruptedException e) { 791 isInterrupted = true; 792 } 793 } 794 } finally { 795 if (isInterrupted) { 796 Thread.currentThread().interrupt(); 797 } 798 } 799 } 800 801 private void writeCacheFile(TreeLogger logger, Compilation compilation) 802 throws UnableToCompleteException { 803 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 807 DocumentBuilder db; 808 try { 809 db = dbf.newDocumentBuilder(); 810 } catch (ParserConfigurationException e) { 811 logger.log(TreeLogger.ERROR, "Unable to construct cache entry XML", e); 812 throw new UnableToCompleteException(); 813 } 814 Document doc = db.newDocument(); 815 816 Element docElem = doc.createElement("cache-entry"); 818 doc.appendChild(docElem); 819 820 String [] genTypeNames = compilation.getGeneratedTypeNames(); 822 for (int i = 0; i < genTypeNames.length; i++) { 823 String genTypeName = genTypeNames[i]; 824 String hash = compilation.getTypeHash(genTypeName); 825 Element childElem = doc.createElement("generated-type-hash"); 826 docElem.appendChild(childElem); 827 childElem.setAttribute("class", genTypeName); 828 childElem.setAttribute("hash", hash); 829 } 830 831 String [] inputs = compilation.getRebindInputs(); 833 for (int i = 0, n = inputs.length; i < n; ++i) { 834 String in = inputs[i]; 835 String out = compilation.getRebindOutput(in); 836 837 Element childElem = doc.createElement("rebind-decision"); 839 docElem.appendChild(childElem); 840 childElem.setAttribute("in", in); 841 childElem.setAttribute("out", out); 842 } 843 844 String strongName = compilation.getStrongName(); 847 File cacheFile = new File (outDir, strongName + EXT_CACHE_XML); 848 byte[] bytes = Util.toXmlUtf8(doc); 849 Util.writeBytesToFile(logger, cacheFile, bytes); 850 851 String msg = "Compilation metadata written to " 852 + cacheFile.getAbsolutePath(); 853 logger.log(TreeLogger.TRACE, msg, null); 854 } 855 856 864 private String writeHtmlAndJsWithStrongName(TreeLogger logger, String js) 865 throws UnableToCompleteException { 866 try { 867 byte[] scriptBytes = js.getBytes("UTF-8"); 868 String strongName = Util.computeStrongName(scriptBytes); 869 { 870 byte[] prefix = getHtmlPrefix().getBytes("UTF-8"); 871 byte[] suffix = getHtmlSuffix().getBytes("UTF-8"); 872 File outFile = new File (outDir, strongName + ".cache.html"); 873 Util.writeBytesToFile(logger, outFile, new byte[][] { 874 prefix, scriptBytes, suffix}); 875 String msg = "Compilation written to " + outFile.getAbsolutePath(); 876 logger.log(TreeLogger.TRACE, msg, null); 877 } 878 { 879 byte[] prefix = getJsPrefix().getBytes("UTF-8"); 880 byte[] suffix = getJsSuffix().getBytes("UTF-8"); 881 File outFile = new File (outDir, strongName + ".cache.js"); 882 Util.writeBytesToFile(logger, outFile, new byte[][] { 883 prefix, scriptBytes, suffix}); 884 String msg = "Compilation written to " + outFile.getAbsolutePath(); 885 logger.log(TreeLogger.TRACE, msg, null); 886 } 887 return strongName; 888 } catch (UnsupportedEncodingException e) { 889 logger.log(TreeLogger.ERROR, "Unable to encode compiled script as UTF-8", 890 e); 891 throw new UnableToCompleteException(); 892 } 893 } 894 895 private void writeSelectionScripts(TreeLogger logger, 896 SelectionScriptGenerator selGen) { 897 { 898 String html = selGen.generateSelectionScript(obfuscate, false); 899 String fn = module.getName() + ".nocache.js"; 900 File selectionFile = new File (outDir, fn); 901 Util.writeStringAsFile(selectionFile, html); 902 String msg = "Compilation selection script written to " 903 + selectionFile.getAbsolutePath(); 904 logger.log(TreeLogger.TRACE, msg, null); 905 } 906 { 907 String html = selGen.generateSelectionScript(obfuscate, true); 908 String fn = module.getName() + "-xs.nocache.js"; 909 File selectionFile = new File (outDir, fn); 910 Util.writeStringAsFile(selectionFile, html); 911 String msg = "Compilation selection script written to " 912 + selectionFile.getAbsolutePath(); 913 logger.log(TreeLogger.TRACE, msg, null); 914 } 915 } 916 } 917 | Popular Tags |