1 21 22 package com.izforge.izpack.installer; 23 24 import java.io.File ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.util.ArrayList ; 28 import java.util.Enumeration ; 29 import java.util.Iterator ; 30 import java.util.LinkedList ; 31 import java.util.List ; 32 import java.util.StringTokenizer ; 33 import java.util.Vector ; 34 35 import net.n3.nanoxml.NonValidator; 36 import net.n3.nanoxml.StdXMLBuilder; 37 import net.n3.nanoxml.StdXMLParser; 38 import net.n3.nanoxml.StdXMLReader; 39 import net.n3.nanoxml.XMLElement; 40 41 import com.izforge.izpack.LocaleDatabase; 42 import com.izforge.izpack.util.Debug; 43 import com.izforge.izpack.util.FileExecutor; 44 import com.izforge.izpack.util.OsConstraint; 45 import com.izforge.izpack.util.VariableSubstitutor; 46 47 59 public class CompileWorker implements Runnable 60 { 61 62 63 private ArrayList jobs; 64 65 66 private static final String SPEC_RESOURCE_NAME = "CompilePanel.Spec.xml"; 67 68 private VariableSubstitutor vs; 69 70 private XMLElement spec; 71 72 private AutomatedInstallData idata; 73 74 private CompileHandler handler; 75 76 private XMLElement compilerSpec; 77 78 private ArrayList compilerList; 79 80 private String compilerToUse; 81 82 private XMLElement compilerArgumentsSpec; 83 84 private ArrayList compilerArgumentsList; 85 86 private String compilerArgumentsToUse; 87 88 private CompileResult result = null; 89 90 96 public CompileWorker(AutomatedInstallData idata, CompileHandler handler) throws IOException 97 { 98 this.idata = idata; 99 this.handler = handler; 100 this.vs = new VariableSubstitutor(idata.getVariables()); 101 102 Thread compilationThread = null; 103 104 if (!readSpec()) throw new IOException ("Error reading compilation specification"); 105 } 106 107 112 public ArrayList getAvailableCompilers() 113 { 114 readChoices(this.compilerSpec, this.compilerList); 115 return this.compilerList; 116 } 117 118 125 public void setCompiler(String compiler) 126 { 127 this.compilerToUse = compiler; 128 } 129 130 131 public String getCompiler() 132 { 133 return this.compilerToUse; 134 } 135 136 141 public ArrayList getAvailableArguments() 142 { 143 readChoices(this.compilerArgumentsSpec, this.compilerArgumentsList); 144 return this.compilerArgumentsList; 145 } 146 147 148 public void setCompilerArguments(String arguments) 149 { 150 this.compilerArgumentsToUse = arguments; 151 } 152 153 154 public String getCompilerArguments() 155 { 156 return this.compilerArgumentsToUse; 157 } 158 159 160 public CompileResult getResult() 161 { 162 return this.result; 163 } 164 165 166 public void startThread() 167 { 168 Thread compilationThread = new Thread (this, "compilation thread"); 169 compilationThread.start(); 171 } 172 173 178 public void run() 179 { 180 try 181 { 182 if (!collectJobs()) 183 { 184 String [] dummy_command = { "no command"}; 185 186 this.result = new CompileResult(this.idata.langpack 187 .getString("CompilePanel.worker.nofiles"), dummy_command, "", ""); 188 } 189 else 190 { 191 this.result = compileJobs(); 192 } 193 } 194 catch (Exception e) 195 { 196 this.result = new CompileResult(); 197 this.result.setStatus(CompileResult.FAILED); 198 this.result.setAction(CompileResult.ACTION_ABORT); 199 } 200 201 this.handler.stopAction(); 202 } 203 204 private boolean readSpec() 205 { 206 InputStream input; 207 try 208 { 209 input = ResourceManager.getInstance().getInputStream(SPEC_RESOURCE_NAME); 210 } 211 catch (Exception e) 212 { 213 e.printStackTrace(); 214 return false; 215 } 216 217 StdXMLParser parser = new StdXMLParser(); 218 parser.setBuilder(new StdXMLBuilder()); 219 parser.setValidator(new NonValidator()); 220 221 try 222 { 223 parser.setReader(new StdXMLReader(input)); 224 225 this.spec = (XMLElement) parser.parse(); 226 } 227 catch (Exception e) 228 { 229 System.out.println("Error parsing XML specification for compilation."); 230 e.printStackTrace(); 231 return false; 232 } 233 234 if (!this.spec.hasChildren()) return false; 235 236 this.compilerArgumentsList = new ArrayList (); 237 this.compilerList = new ArrayList (); 238 239 XMLElement global = this.spec.getFirstChildNamed("global"); 241 242 if (global != null) 244 { 245 246 this.compilerSpec = global.getFirstChildNamed("compiler"); 248 249 if (this.compilerSpec != null) 250 { 251 readChoices(this.compilerSpec, this.compilerList); 252 } 253 254 this.compilerArgumentsSpec = global.getFirstChildNamed("arguments"); 255 256 if (this.compilerArgumentsSpec != null) 257 { 258 readChoices(this.compilerArgumentsSpec, this.compilerArgumentsList); 260 } 261 262 } 263 264 if (this.compilerList.size() == 0) 266 { 267 this.compilerList.add("javac"); 268 this.compilerList.add("jikes"); 269 } 270 271 if (this.compilerArgumentsList.size() == 0) 272 { 273 this.compilerArgumentsList.add("-O -g:none"); 274 this.compilerArgumentsList.add("-O"); 275 this.compilerArgumentsList.add("-g"); 276 this.compilerArgumentsList.add(""); 277 } 278 279 return true; 280 } 281 282 private void readChoices(XMLElement element, ArrayList result) 284 { 285 Vector choices = element.getChildrenNamed("choice"); 286 287 if (choices == null) return; 288 289 result.clear(); 290 291 Iterator choice_it = choices.iterator(); 292 293 while (choice_it.hasNext()) 294 { 295 XMLElement choice = (XMLElement) choice_it.next(); 296 297 String value = choice.getAttribute("value"); 298 299 if (value != null) 300 { 301 List osconstraints = OsConstraint.getOsList(choice); 302 303 if (OsConstraint.oneMatchesCurrentSystem(osconstraints)) 304 { 305 result.add(this.vs.substitute(value, "plain")); 306 } 307 } 308 309 } 310 311 } 312 313 316 private boolean collectJobs() throws Exception 317 { 318 XMLElement data = this.spec.getFirstChildNamed("jobs"); 319 320 if (data == null) return false; 321 322 ArrayList classpath = new ArrayList (); 324 325 this.jobs = new ArrayList (); 326 327 collectJobsRecursive(data, classpath); 330 331 return true; 332 } 333 334 335 private CompileResult compileJobs() 336 { 337 ArrayList args = new ArrayList (); 338 StringTokenizer tokenizer = new StringTokenizer (this.compilerArgumentsToUse); 339 340 while (tokenizer.hasMoreTokens()) 341 { 342 args.add(tokenizer.nextToken()); 343 } 344 345 Iterator job_it = this.jobs.iterator(); 346 347 this.handler.startAction("Compilation", this.jobs.size()); 348 349 if (job_it.hasNext()) 351 { 352 CompilationJob first_job = (CompilationJob) this.jobs.get(0); 353 354 CompileResult check_result = first_job.checkCompiler(this.compilerToUse, args); 355 if (!check_result.isContinue()) { return check_result; } 356 357 } 358 359 int job_no = 0; 360 361 while (job_it.hasNext()) 362 { 363 CompilationJob job = (CompilationJob) job_it.next(); 364 365 this.handler.nextStep(job.getName(), job.getSize(), job_no++); 366 367 CompileResult result = job.perform(this.compilerToUse, args); 368 369 if (!result.isContinue()) return result; 370 } 371 372 Debug.trace("compilation finished."); 373 return new CompileResult(); 374 } 375 376 private CompilationJob collectJobsRecursive(XMLElement node, ArrayList classpath) 377 throws Exception 378 { 379 Enumeration toplevel_tags = node.enumerateChildren(); 380 ArrayList ourclasspath = (ArrayList ) classpath.clone(); 381 ArrayList files = new ArrayList (); 382 383 while (toplevel_tags.hasMoreElements()) 384 { 385 XMLElement child = (XMLElement) toplevel_tags.nextElement(); 386 387 if ("classpath".equals(child.getName())) 388 { 389 changeClassPath(ourclasspath, child); 390 } 391 else if ("job".equals(child.getName())) 392 { 393 CompilationJob subjob = collectJobsRecursive(child, ourclasspath); 394 if (subjob != null) this.jobs.add(subjob); 395 } 396 else if ("directory".equals(child.getName())) 397 { 398 String name = child.getAttribute("name"); 399 400 if (name != null) 401 { 402 String finalname = this.vs.substitute(name, "plain"); 404 405 files.addAll(scanDirectory(new File (finalname))); 406 } 407 408 } 409 else if ("file".equals(child.getName())) 410 { 411 String name = child.getAttribute("name"); 412 413 if (name != null) 414 { 415 String finalname = this.vs.substitute(name, "plain"); 417 418 files.add(new File (finalname)); 419 } 420 421 } 422 else if ("packdepency".equals(child.getName())) 423 { 424 String name = child.getAttribute("name"); 425 426 if (name == null) 427 { 428 System.out 429 .println("invalid compilation spec: <packdepency> without name attribute"); 430 return null; 431 } 432 433 Iterator pack_it = this.idata.selectedPacks.iterator(); 435 boolean found = false; 436 437 while (pack_it.hasNext()) 438 { 439 com.izforge.izpack.Pack pack = (com.izforge.izpack.Pack) pack_it.next(); 440 441 if (pack.name.equals(name)) 442 { 443 found = true; 444 break; 445 } 446 } 447 448 if (!found) 449 { 450 Debug.trace("skipping job because pack " + name + " was not selected."); 451 return null; 452 } 453 454 } 455 456 } 457 458 if (files.size() > 0) 459 return new CompilationJob(this.handler, this.idata.langpack, (String ) node 460 .getAttribute("name"), files, ourclasspath); 461 462 return null; 463 } 464 465 466 private void changeClassPath(ArrayList classpath, XMLElement child) throws Exception 467 { 468 String add = child.getAttribute("add"); 469 if (add != null) 470 { 471 add = this.vs.substitute(add, "plain"); 472 if (!new File (add).exists()) 473 { 474 if (!this.handler.emitWarning("Invalid classpath", "The path " + add 475 + " could not be found.\nCompilation may fail.")) 476 throw new Exception ("Classpath " + add + " does not exist."); 477 } 478 else 479 { 480 classpath.add(this.vs.substitute(add, "plain")); 481 } 482 483 } 484 485 String sub = child.getAttribute("sub"); 486 if (sub != null) 487 { 488 int cpidx = -1; 489 sub = this.vs.substitute(sub, "plain"); 490 491 do 492 { 493 cpidx = classpath.indexOf(sub); 494 classpath.remove(cpidx); 495 } 496 while (cpidx >= 0); 497 498 } 499 500 } 501 502 507 private ArrayList scanDirectory(File path) 508 { 509 Debug.trace("scanning directory " + path.getAbsolutePath()); 510 511 ArrayList result = new ArrayList (); 512 513 if (!path.isDirectory()) return result; 514 515 File [] entries = path.listFiles(); 516 517 for (int i = 0; i < entries.length; i++) 518 { 519 File f = entries[i]; 520 521 if (f == null) continue; 522 523 if (f.isDirectory()) 524 { 525 result.addAll(scanDirectory(f)); 526 } 527 else if ((f.isFile()) && (f.getName().toLowerCase().endsWith(".java"))) 528 { 529 result.add(f); 530 } 531 532 } 533 534 return result; 535 } 536 537 538 private static class CompilationJob 539 { 540 541 private CompileHandler listener; 542 543 private String name; 544 545 private ArrayList files; 546 547 private ArrayList classpath; 548 549 private LocaleDatabase langpack; 550 551 private static final int MAX_CMDLINE_SIZE = 4096; 553 554 public CompilationJob(CompileHandler listener, LocaleDatabase langpack, ArrayList files, 555 ArrayList classpath) 556 { 557 this.listener = listener; 558 this.langpack = langpack; 559 this.name = null; 560 this.files = files; 561 this.classpath = classpath; 562 } 563 564 public CompilationJob(CompileHandler listener, LocaleDatabase langpack, String name, 565 ArrayList files, ArrayList classpath) 566 { 567 this.listener = listener; 568 this.langpack = langpack; 569 this.name = name; 570 this.files = files; 571 this.classpath = classpath; 572 } 573 574 public String getName() 575 { 576 if (this.name != null) return this.name; 577 578 return ""; 579 } 580 581 public int getSize() 582 { 583 return this.files.size(); 584 } 585 586 public CompileResult perform(String compiler, ArrayList arguments) 587 { 588 Debug.trace("starting job " + this.name); 589 int cmdline_len = 0; 591 592 LinkedList args = new LinkedList (arguments); 594 595 { 596 Iterator arg_it = args.iterator(); 597 while (arg_it.hasNext()) 598 cmdline_len += ((String ) arg_it.next()).length() + 1; 599 } 600 601 args.add(0, compiler); 603 cmdline_len += compiler.length() + 1; 604 605 StringBuffer classpath_sb = new StringBuffer (); 608 Iterator cp_it = this.classpath.iterator(); 609 while (cp_it.hasNext()) 610 { 611 String cp = (String ) cp_it.next(); 612 if (classpath_sb.length() > 0) classpath_sb.append(File.pathSeparatorChar); 613 classpath_sb.append(new File (cp).getAbsolutePath()); 614 } 615 616 String classpath_str = classpath_sb.toString(); 617 618 if (classpath_str.length() > 0) 620 { 621 args.add("-classpath"); 622 cmdline_len += 11; 623 args.add(classpath_str); 624 cmdline_len += classpath_str.length() + 1; 625 } 626 627 int common_args_no = args.size(); 630 int common_args_len = cmdline_len; 632 633 FileExecutor executor = new FileExecutor(); 635 String output[] = new String [2]; 636 637 String jobfiles = ""; 639 int fileno = 0; 640 int last_fileno = 0; 641 642 Iterator file_it = this.files.iterator(); 644 645 while (file_it.hasNext()) 646 { 647 File f = (File ) file_it.next(); 648 649 String fpath = f.getAbsolutePath(); 650 651 Debug.trace("processing " + fpath); 652 653 fileno++; 657 jobfiles += f.getName() + " "; 658 args.add(fpath); 659 cmdline_len += fpath.length(); 660 661 if (cmdline_len >= MAX_CMDLINE_SIZE) 663 { 664 Debug.trace("compiling " + jobfiles); 665 666 this.listener.progress(last_fileno, jobfiles); 670 last_fileno = fileno; 671 672 String [] full_cmdline = (String []) args.toArray(output); 673 674 int retval = executor.executeCommand(full_cmdline, output); 675 676 this.listener.progress(fileno, jobfiles); 678 679 if (retval != 0) 680 { 681 CompileResult result = new CompileResult(this.langpack 682 .getString("CompilePanel.error"), full_cmdline, output[0], 683 output[1]); 684 this.listener.handleCompileError(result); 685 if (!result.isContinue()) return result; 686 } 687 else 688 { 689 Iterator arg_it = args.listIterator(common_args_no); 694 while (arg_it.hasNext()) 695 { 696 File java_file = new File ((String ) arg_it.next()); 697 698 String basename = java_file.getName(); 699 int dotpos = basename.lastIndexOf('.'); 700 basename = basename.substring(0, dotpos) + ".class"; 701 File class_file = new File (java_file.getParentFile(), basename); 702 703 if (!class_file.exists()) 704 { 705 CompileResult result = new CompileResult(this.langpack 706 .getString("CompilePanel.error.noclassfile") 707 + java_file.getAbsolutePath(), full_cmdline, output[0], 708 output[1]); 709 this.listener.handleCompileError(result); 710 if (!result.isContinue()) return result; 711 break; 713 } 714 715 } 716 717 } 718 719 for (int i = args.size() - 1; i >= common_args_no; i--) 721 { 722 args.removeLast(); 723 } 724 725 cmdline_len = common_args_len; 726 jobfiles = ""; 727 } 728 729 } 730 731 if (cmdline_len > common_args_len) 732 { 733 this.listener.progress(last_fileno, jobfiles); 734 735 String [] full_cmdline = (String []) args.toArray(output); 736 737 int retval = executor.executeCommand(full_cmdline, output); 738 739 this.listener.progress(fileno, jobfiles); 740 741 if (retval != 0) 742 { 743 CompileResult result = new CompileResult(this.langpack 744 .getString("CompilePanel.error"), full_cmdline, output[0], output[1]); 745 this.listener.handleCompileError(result); 746 if (!result.isContinue()) return result; 747 } 748 749 } 750 751 Debug.trace("job " + this.name + " done (" + fileno + " files compiled)"); 752 753 return new CompileResult(); 754 } 755 756 773 public CompileResult checkCompiler(String compiler, ArrayList arguments) 774 { 775 int retval = 0; 776 FileExecutor executor = new FileExecutor(); 777 String [] output = new String [2]; 778 779 Debug.trace("checking whether \"" + compiler + " -help\" works"); 780 781 { 782 String [] args = { compiler, "-help"}; 783 784 retval = executor.executeCommand(args, output); 785 786 if (retval != 0) 787 { 788 CompileResult result = new CompileResult(this.langpack 789 .getString("CompilePanel.error.compilernotfound"), args, output[0], 790 output[1]); 791 this.listener.handleCompileError(result); 792 if (!result.isContinue()) return result; 793 } 794 } 795 796 Debug.trace("checking whether \"" + compiler + " -help +arguments\" works"); 797 798 LinkedList args = new LinkedList (arguments); 800 801 args.add(0, "-help"); 803 804 args.add(0, compiler); 806 807 StringBuffer classpath_sb = new StringBuffer (); 810 Iterator cp_it = this.classpath.iterator(); 811 while (cp_it.hasNext()) 812 { 813 String cp = (String ) cp_it.next(); 814 if (classpath_sb.length() > 0) classpath_sb.append(File.pathSeparatorChar); 815 classpath_sb.append(new File (cp).getAbsolutePath()); 816 } 817 818 String classpath_str = classpath_sb.toString(); 819 820 if (classpath_str.length() > 0) 822 { 823 args.add("-classpath"); 824 args.add(classpath_str); 825 } 826 827 String [] args_arr = (String []) args.toArray(output); 828 829 retval = executor.executeCommand(args_arr, output); 830 831 if (retval != 0) 832 { 833 CompileResult result = new CompileResult(this.langpack 834 .getString("CompilePanel.error.invalidarguments"), args_arr, output[0], 835 output[1]); 836 this.listener.handleCompileError(result); 837 if (!result.isContinue()) return result; 838 } 839 840 return new CompileResult(); 841 } 842 843 } 844 845 } 846 | Popular Tags |