1 21 22 package com.izforge.izpack.installer; 23 24 import java.io.BufferedReader ; 25 import java.io.File ; 26 import java.io.FileOutputStream ; 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.InputStreamReader ; 30 import java.io.PrintWriter ; 31 import java.lang.reflect.InvocationTargetException ; 32 import java.lang.reflect.Method ; 33 import java.text.SimpleDateFormat ; 34 import java.util.ArrayList ; 35 import java.util.Date ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.Vector ; 39 40 import net.n3.nanoxml.NonValidator; 41 import net.n3.nanoxml.StdXMLBuilder; 42 import net.n3.nanoxml.StdXMLParser; 43 import net.n3.nanoxml.StdXMLReader; 44 import net.n3.nanoxml.XMLElement; 45 46 import com.izforge.izpack.Pack; 47 import com.izforge.izpack.util.AbstractUIHandler; 48 import com.izforge.izpack.util.AbstractUIProcessHandler; 49 import com.izforge.izpack.util.Debug; 50 import com.izforge.izpack.util.IoHelper; 51 import com.izforge.izpack.util.OsConstraint; 52 import com.izforge.izpack.util.VariableSubstitutor; 53 54 65 public class ProcessPanelWorker implements Runnable 66 { 67 68 69 private static final String SPEC_RESOURCE_NAME = "ProcessPanel.Spec.xml"; 70 71 private VariableSubstitutor vs; 72 73 protected AbstractUIProcessHandler handler; 74 75 private ArrayList jobs = new ArrayList (); 76 77 private boolean result = true; 78 79 private static PrintWriter logfile = null; 80 81 private String logfiledir = null; 82 83 protected AutomatedInstallData idata; 84 85 91 public ProcessPanelWorker(AutomatedInstallData idata, AbstractUIProcessHandler handler) 92 throws IOException 93 { 94 this.handler = handler; 95 this.idata = idata; 96 this.vs = new VariableSubstitutor(idata.getVariables()); 97 98 } 103 104 private boolean readSpec() throws IOException 105 { 106 InputStream input; 107 try 108 { 109 input = ResourceManager.getInstance().getInputStream(SPEC_RESOURCE_NAME); 110 } 111 catch (Exception e) 112 { 113 e.printStackTrace(); 114 return false; 115 } 116 117 StdXMLParser parser = new StdXMLParser(); 118 parser.setBuilder(new StdXMLBuilder()); 119 parser.setValidator(new NonValidator()); 120 121 XMLElement spec; 122 try 123 { 124 parser.setReader(new StdXMLReader(input)); 125 126 spec = (XMLElement) parser.parse(); 127 } 128 catch (Exception e) 129 { 130 System.err.println("Error parsing XML specification for processing."); 131 System.err.println(e.toString()); 132 return false; 133 } 134 135 if (!spec.hasChildren()) return false; 136 137 XMLElement lfd = spec.getFirstChildNamed("logfiledir"); 139 if (lfd != null) 140 { 141 logfiledir = lfd.getContent(); 142 } 143 144 for (Iterator job_it = spec.getChildrenNamed("job").iterator(); job_it.hasNext();) 145 { 146 XMLElement job_el = (XMLElement) job_it.next(); 147 148 Vector forPacks = job_el.getChildrenNamed("executeForPack"); 151 if (!jobRequiredFor(forPacks)) 152 { 153 continue; 154 } 155 156 List constraints = OsConstraint.getOsList(job_el); 158 159 if (OsConstraint.oneMatchesCurrentSystem(constraints)) 160 { 161 List ef_list = new ArrayList (); 162 163 String job_name = job_el.getAttribute("name", ""); 164 165 for (Iterator ef_it = job_el.getChildrenNamed("executefile").iterator(); ef_it 166 .hasNext();) 167 { 168 XMLElement ef = (XMLElement) ef_it.next(); 169 170 String ef_name = ef.getAttribute("name"); 171 172 if ((ef_name == null) || (ef_name.length() == 0)) 173 { 174 System.err.println("missing \"name\" attribute for <executefile>"); 175 return false; 176 } 177 178 List args = new ArrayList (); 179 180 for (Iterator arg_it = ef.getChildrenNamed("arg").iterator(); arg_it.hasNext();) 181 { 182 XMLElement arg_el = (XMLElement) arg_it.next(); 183 184 String arg_val = arg_el.getContent(); 185 186 args.add(arg_val); 187 } 188 189 ef_list.add(new ExecutableFile(ef_name, args)); 190 } 191 192 for (Iterator ef_it = job_el.getChildrenNamed("executeclass").iterator(); ef_it 193 .hasNext();) 194 { 195 XMLElement ef = (XMLElement) ef_it.next(); 196 String ef_name = ef.getAttribute("name"); 197 if ((ef_name == null) || (ef_name.length() == 0)) 198 { 199 System.err.println("missing \"name\" attribute for <executeclass>"); 200 return false; 201 } 202 203 List args = new ArrayList (); 204 for (Iterator arg_it = ef.getChildrenNamed("arg").iterator(); arg_it.hasNext();) 205 { 206 XMLElement arg_el = (XMLElement) arg_it.next(); 207 String arg_val = arg_el.getContent(); 208 args.add(arg_val); 209 } 210 211 ef_list.add(new ExecutableClass(ef_name, args)); 212 } 213 this.jobs.add(new ProcessingJob(job_name, ef_list)); 214 } 215 216 } 217 218 return true; 219 } 220 221 226 public void run() 227 { 228 try 232 { 233 if (!readSpec()) 234 { 235 System.err.println("Error parsing XML specification for processing."); 236 return; 237 } 238 } 239 catch (java.io.IOException ioe) 240 { 241 System.err.println(ioe.toString()); 242 return; 243 } 244 245 if (logfiledir != null) 248 { 249 logfiledir = IoHelper.translatePath(logfiledir, new VariableSubstitutor(idata 250 .getVariables())); 251 252 File lf; 253 254 String appVersion = idata.getVariable("APP_VER"); 255 256 if (appVersion != null) 257 appVersion = "V" + appVersion; 258 else 259 appVersion = "undef"; 260 261 String identifier = (new SimpleDateFormat ("yyyyMMddHHmmss")).format(new Date ()); 262 263 identifier = appVersion.replace(' ', '_') + "_" + identifier; 264 265 try 266 { 267 lf = File.createTempFile("Install_" + identifier + "_", ".log", 268 new File (logfiledir)); 269 logfile = new PrintWriter (new FileOutputStream (lf), true); 270 } 271 catch (IOException e) 272 { 273 Debug.error(e); 274 } 276 } 277 278 this.handler.startProcessing(this.jobs.size()); 279 280 for (Iterator job_it = this.jobs.iterator(); job_it.hasNext();) 281 { 282 ProcessingJob pj = (ProcessingJob) job_it.next(); 283 284 this.handler.startProcess(pj.name); 285 286 this.result = pj.run(this.handler, this.vs); 287 288 this.handler.finishProcess(); 289 290 if (!this.result) break; 291 } 292 293 this.handler.finishProcessing(); 294 if (logfile != null) logfile.close(); 295 } 296 297 298 public void startThread() 299 { 300 Thread processingThread = new Thread (this, "processing thread"); 301 processingThread.start(); 303 } 304 305 310 public boolean getResult() 311 { 312 return this.result; 313 } 314 315 interface Processable 316 { 317 318 322 public boolean run(AbstractUIProcessHandler handler, VariableSubstitutor vs); 323 } 324 325 private static class ProcessingJob implements Processable 326 { 327 328 public String name; 329 330 private List processables; 331 332 public ProcessingJob(String name, List processables) 333 { 334 this.name = name; 335 this.processables = processables; 336 } 337 338 public boolean run(AbstractUIProcessHandler handler, VariableSubstitutor vs) 339 { 340 for (Iterator pr_it = this.processables.iterator(); pr_it.hasNext();) 341 { 342 Processable pr = (Processable) pr_it.next(); 343 344 if (!pr.run(handler, vs)) return false; 345 } 346 347 return true; 348 } 349 350 } 351 352 private static class ExecutableFile implements Processable 353 { 354 355 private String filename; 356 357 private List arguments; 358 359 protected AbstractUIProcessHandler handler; 360 361 public ExecutableFile(String fn, List args) 362 { 363 this.filename = fn; 364 this.arguments = args; 365 } 366 367 public boolean run(AbstractUIProcessHandler handler, VariableSubstitutor vs) 368 { 369 this.handler = handler; 370 371 String params[] = new String [this.arguments.size() + 1]; 372 373 params[0] = vs.substitute(this.filename, "plain"); 374 375 int i = 1; 376 for (Iterator arg_it = this.arguments.iterator(); arg_it.hasNext();) 377 { 378 params[i++] = vs.substitute((String ) arg_it.next(), "plain"); 379 } 380 381 try 382 { 383 Process p = Runtime.getRuntime().exec(params); 384 385 OutputMonitor stdoutMon = new OutputMonitor(this.handler, p.getInputStream(), false); 386 OutputMonitor stderrMon = new OutputMonitor(this.handler, p.getErrorStream(), true); 387 Thread stdoutThread = new Thread (stdoutMon); 388 Thread stderrThread = new Thread (stderrMon); 389 stdoutThread.setDaemon(true); 390 stderrThread.setDaemon(true); 391 stdoutThread.start(); 392 stderrThread.start(); 393 394 try 395 { 396 int exitStatus = p.waitFor(); 397 398 stopMonitor(stdoutMon, stdoutThread); 399 stopMonitor(stderrMon, stderrThread); 400 401 if (exitStatus != 0) 402 { 403 if (this.handler.askQuestion("process execution failed", 404 "Continue anyway?", AbstractUIHandler.CHOICES_YES_NO, 405 AbstractUIHandler.ANSWER_YES) == AbstractUIHandler.ANSWER_NO) { return false; } 406 } 407 } 408 catch (InterruptedException ie) 409 { 410 p.destroy(); 411 this.handler.emitError("process interrupted", ie.toString()); 412 return false; 413 } 414 } 415 catch (IOException ioe) 416 { 417 this.handler.emitError("I/O error", ioe.toString()); 418 return false; 419 } 420 421 return true; 422 } 423 424 private void stopMonitor(OutputMonitor m, Thread t) 425 { 426 m.doStop(); 428 long softTimeout = 500; 429 try 430 { 431 t.join(softTimeout); 432 } 433 catch (InterruptedException e) 434 {} 435 436 if (!t.isAlive()) return; 437 438 t.interrupt(); 439 long hardTimeout = 500; 440 try 441 { 442 t.join(hardTimeout); 443 } 444 catch (InterruptedException e) 445 {} 446 } 447 448 static public class OutputMonitor implements Runnable 449 { 450 451 private boolean stderr = false; 452 453 private AbstractUIProcessHandler handler; 454 455 private BufferedReader reader; 456 457 private Boolean stop = Boolean.valueOf(false); 458 459 public OutputMonitor(AbstractUIProcessHandler handler, InputStream is, boolean stderr) 460 { 461 this.stderr = stderr; 462 this.reader = new BufferedReader (new InputStreamReader (is)); 463 this.handler = handler; 464 } 465 466 public void run() 467 { 468 try 469 { 470 String line; 471 while ((line = reader.readLine()) != null) 472 { 473 this.handler.logOutput(line, stderr); 474 475 477 if (logfile != null) logfile.println(line); 478 479 synchronized (this.stop) 480 { 481 if (stop.booleanValue()) return; 482 } 483 } 484 } 485 catch (IOException ioe) 486 { 487 this.handler.logOutput(ioe.toString(), true); 488 489 491 if (logfile != null) logfile.println(ioe.toString()); 492 493 } 494 495 } 496 497 public void doStop() 498 { 499 synchronized (this.stop) 500 { 501 this.stop = Boolean.valueOf(true); 502 } 503 } 504 505 } 506 507 } 508 509 514 private static class ExecutableClass implements Processable 515 { 516 517 final private String myClassName; 518 519 final private List myArguments; 520 521 protected AbstractUIProcessHandler myHandler; 522 523 public ExecutableClass(String className, List args) 524 { 525 myClassName = className; 526 myArguments = args; 527 } 528 529 public boolean run(AbstractUIProcessHandler aHandler, VariableSubstitutor varSubstitutor) 530 { 531 boolean result = false; 532 myHandler = aHandler; 533 534 String params[] = new String [myArguments.size()]; 535 536 int i = 0; 537 for (Iterator arg_it = myArguments.iterator(); arg_it.hasNext();) 538 params[i++] = varSubstitutor.substitute((String ) arg_it.next(), "plain"); 539 540 try 541 { 542 ClassLoader loader = this.getClass().getClassLoader(); 543 Class procClass = loader.loadClass(myClassName); 544 545 Object o = procClass.newInstance(); 546 Method m = procClass.getMethod("run", new Class [] { AbstractUIProcessHandler.class, 547 String [].class}); 548 549 m.invoke(o, new Object [] { myHandler, params}); 550 result = true; 551 } 552 catch (SecurityException e) 553 { 554 myHandler.emitError("Post Processing Error", 555 "Security exception thrown when processing class: " + myClassName); 556 } 557 catch (ClassNotFoundException e) 558 { 559 myHandler.emitError("Post Processing Error", "Cannot find processing class: " 560 + myClassName); 561 } 562 catch (NoSuchMethodException e) 563 { 564 myHandler.emitError("Post Processing Error", 565 "Processing class does not have 'run' method: " + myClassName); 566 } 567 catch (IllegalAccessException e) 568 { 569 myHandler.emitError("Post Processing Error", "Error accessing processing class: " 570 + myClassName); 571 } 572 catch (InvocationTargetException e) 573 { 574 myHandler.emitError("Post Processing Error", "Invocation Problem calling : " 575 + myClassName + ", " + e.getCause().getMessage()); 576 } 577 catch (Exception e) 578 { 579 myHandler.emitError("Post Processing Error", 580 "Exception when running processing class: " + myClassName + ", " 581 + e.getMessage()); 582 } 583 catch (Error e) 584 { 585 myHandler.emitError("Post Processing Error", 586 "Error when running processing class: " + myClassName + ", " 587 + e.getMessage()); 588 } 589 catch (Throwable e) 590 { 591 myHandler.emitError("Post Processing Error", 592 "Error when running processing class: " + myClassName + ", " 593 + e.getMessage()); 594 } 595 return result; 596 } 597 } 598 599 600 612 613 621 622 private boolean jobRequiredFor(Vector packs) 623 { 624 String selected; 625 String required; 626 627 if (packs.size() == 0) { return (true); } 628 629 632 for (int i = 0; i < idata.selectedPacks.size(); i++) 633 { 634 selected = ((Pack) idata.selectedPacks.get(i)).name; 635 636 638 for (int k = 0; k < packs.size(); k++) 639 { 640 required = (String ) ((XMLElement) packs.elementAt(k)).getAttribute("name", ""); 641 if (selected.equals(required)) 643 { 644 return (true); 646 } 647 } 648 } 649 return (false); 650 } 651 652 } 653 | Popular Tags |