1 19 20 package org.netbeans.modules.versioning.system.cvss; 21 22 import org.netbeans.lib.cvsclient.CVSRoot; 23 import org.netbeans.lib.cvsclient.event.*; 24 import org.netbeans.lib.cvsclient.command.*; 25 import org.netbeans.modules.versioning.system.cvss.util.Utils; 26 import org.netbeans.modules.versioning.system.cvss.util.CommandDuplicator; 27 import org.netbeans.modules.versioning.system.cvss.ui.wizards.RootWizard; 28 import org.netbeans.modules.versioning.system.cvss.ui.UIUtils; 29 import org.openide.ErrorManager; 30 import org.openide.DialogDescriptor; 31 import org.openide.DialogDisplayer; 32 import org.openide.NotifyDescriptor; 33 import org.openide.filesystems.FileUtil; 34 import org.openide.util.RequestProcessor; 35 import org.openide.util.NbBundle; 36 import org.openide.util.TaskListener; 37 38 import javax.swing.*; 39 import javax.swing.event.ChangeListener ; 40 import javax.swing.event.ChangeEvent ; 41 import java.util.*; 42 import java.util.List ; 43 import java.io.IOException ; 44 import java.io.File ; 45 import java.io.StringWriter ; 46 import java.io.PrintWriter ; 47 import java.awt.*; 48 import java.awt.event.ActionEvent ; 49 import java.awt.event.ActionListener ; 50 import java.text.MessageFormat ; 51 import org.openide.xml.XMLUtil; 52 53 68 public abstract class ExecutorSupport implements CVSListener, ExecutorGroup.Groupable { 69 70 74 private static final String [] ignoredMessagePrefixes = {"cvs server: Updating", "cvs server: New directory"}; 76 protected final FileStatusCache cache; 77 78 84 protected List toRefresh = new ArrayList(10); 85 86 protected final CvsVersioningSystem cvs; 87 protected final Command cmd; 88 private final GlobalOptions options; 89 private RequestProcessor.Task task; 90 private List taskListeners = new ArrayList(2); 91 private Throwable internalError; 92 private boolean terminated; 93 private boolean commandFailed; 94 95 private boolean finishedExecution; 96 private boolean executed; 97 private CommandRunnable commandRunnable; 98 99 private StringBuffer message = new StringBuffer (); 100 private ClientRuntime clientRuntime; 101 private List errorMessages = new ArrayList(); 102 private List warningMessages = new ArrayList(); 103 104 private ExecutorGroup group; 105 106 107 boolean t9yRetryFlag; 108 109 112 private boolean nonInteractive; 113 114 120 protected ExecutorSupport(CvsVersioningSystem cvs, Command cmd, GlobalOptions options) { 121 this.cvs = cvs; 122 this.cmd = cmd; 123 this.options = options; 124 cache = cvs.getStatusCache(); 125 } 126 127 protected void setNonInteractive(boolean nonInteractive) { 128 this.nonInteractive = nonInteractive; 129 } 130 131 132 137 public void execute() { 138 assert executed == false; 139 executed = true; 140 if (group == null) { 141 group = new ExecutorGroup(getDisplayName()); 142 group.setNonInteractive(nonInteractive); 143 } 144 145 setup(); 146 executeImpl(); 147 } 148 149 private void executeImpl() { 150 try { 151 task = cvs.post(cmd, options, this); 152 } catch (Throwable e) { 153 internalError = e; 154 group.fail(); 155 156 String msg = NbBundle.getMessage(ExecutorSupport.class, "BK1003", new Date(), getDisplayName()); 157 if (clientRuntime != null) { clientRuntime.log(msg + "\n"); clientRuntime.logError(e); 160 } 161 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 162 synchronized(this) { 163 finishedExecution = true; 164 notifyAll(); 165 } 166 cleanup(); 167 } 168 } 169 170 173 protected void setup() { 174 } 175 176 179 protected void cleanup() { 180 } 181 182 190 protected String getDisplayName() { 191 String commandName; 192 if (group != null) { 193 commandName = group.getDisplayName(); 194 } else { 195 commandName = cmd.getDisplayName(); 196 if (commandName == null) { 197 commandName = cmd.getCVSCommand(); 198 } 199 } 200 return commandName; 201 } 202 203 207 protected boolean logCommandOutput() { 208 return true; 209 } 210 211 public void joinGroup(ExecutorGroup group) { 212 assert executed == false; 213 this.group = group; 214 } 215 216 public ExecutorGroup getGroup() { 217 return group; 218 } 219 220 224 public Throwable getFailure() { 225 return internalError; 226 } 227 228 231 public boolean isCancelled() { 232 return group.isCancelled(); 233 } 234 235 238 public boolean isSuccessful() { 239 return internalError == null && group.isCancelled() == false && commandFailed == false; 240 } 241 242 243 public RequestProcessor.Task getTask() { 244 return task; 245 } 246 247 public void messageSent(MessageEvent e) { 248 if (e.isError()) { 249 String msg = e.getMessage(); 250 if (msg == null) { 251 RuntimeException rex = new RuntimeException ("Received null MessageEvent from:"); StringWriter sw = new StringWriter (); 254 PrintWriter pw = new PrintWriter (sw); 255 rex.printStackTrace(pw); 256 pw.close(); 257 msg = sw.getBuffer().toString(); 258 } 259 errorMessages.add(msg); 260 } 261 else if (e.getMessage().startsWith("W ")) { warningMessages.add(e.getMessage().substring(2)); 263 } 264 if (e.isTagged()) { 265 String s = MessageEvent.parseTaggedMessage(message, e.getMessage()); 266 if (s != null) { 267 clientRuntime.log(s + "\n"); message.setLength(0); 269 } 270 } else { 271 boolean locked = e.getMessage().indexOf("waiting for") != -1; locked &= e.getMessage().indexOf("lock in") != -1; if (locked || logCommandOutput()) { 276 if (e.getMessage().length() > 0) { if (shouldBeDisplayed(e.getMessage())) { 278 clientRuntime.log(e.getMessage() + "\n"); } 280 } 281 } 282 } 283 } 284 285 private boolean shouldBeDisplayed(String message) { 286 for (int i = 0; i < ignoredMessagePrefixes.length; i++) { 287 if (message.startsWith(ignoredMessagePrefixes[i])) return false; 288 } 289 return true; 290 } 291 292 public void messageSent(BinaryMessageEvent e) { 293 } 294 295 public void fileAdded(FileAddedEvent e) { 296 } 297 298 public void fileRemoved(FileRemovedEvent e) { 299 } 300 301 public void fileUpdated(FileUpdatedEvent e) { 302 } 303 304 public void fileToRemove(FileToRemoveEvent e) { 305 } 306 307 public void fileInfoGenerated(FileInfoEvent e) { 308 assert !terminated; 309 FileInfoContainer fic = e.getInfoContainer(); 310 if (fic.getFile() == null) { 311 ErrorManager.getDefault().log(ErrorManager.WARNING, org.netbeans.modules.versioning.util.Utils.getStackTrace()); 313 return; 314 } 315 if (fic instanceof DefaultFileInfoContainer) { 316 DefaultFileInfoContainer dfic = ((DefaultFileInfoContainer) fic); 317 dfic.setFile(FileUtil.normalizeFile(dfic.getFile())); 318 for (Iterator i = toRefresh.iterator(); i.hasNext();) { 321 FileInfoContainer existing = (FileInfoContainer) i.next(); 322 if (existing.getFile().equals(fic.getFile())) { 323 String existingType = ((DefaultFileInfoContainer) existing).getType(); 324 String newType = dfic.getType(); 325 if (importance(newType) <= importance(existingType)) return; 326 i.remove(); 327 break; 328 } 329 } 330 } 331 toRefresh.add(fic); 332 } 333 334 private int importance(String type) { 335 return "UC".indexOf(type); } 337 338 344 public void commandEnqueued(CommandRunnable commandRunnable) { 345 this.commandRunnable = commandRunnable; 346 group.enqueued(cvs.getClientRuntime(cmd, options), this); 347 group.addCancellable(commandRunnable); 348 } 349 350 353 public void commandStarted(CommandRunnable commandRunnable) { 354 clientRuntime = cvs.getClientRuntime(cmd, options); 355 group.started(clientRuntime); 356 } 357 358 public void commandTerminated(TerminationEvent e) { 359 try { 360 if (e.getSource() instanceof ClientRuntime.Result) { 361 assert !terminated; 362 terminated = true; 363 ClientRuntime.Result result = (ClientRuntime.Result) e.getSource(); 364 Throwable error = result.getError(); 365 if (result.isAborted() || Thread.currentThread().isInterrupted()) { 366 toRefresh.clear(); 367 return; 368 } else if (error != null) { 369 toRefresh.clear(); 370 if (error instanceof CommandException) { 371 internalError = error; 374 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, error); 375 report(NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandFailed_Title"), 376 NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandFailed_Prompt"), 377 Arrays.asList(new String [] { error.getMessage() }), NotifyDescriptor.ERROR_MESSAGE); 378 } 379 else if (!nonInteractive && retryConnection(error)) { 380 terminated = false; 381 String msg = NbBundle.getMessage(ExecutorSupport.class, "BK1004", new Date(), getDisplayName()); 382 clientRuntime = cvs.getClientRuntime(cmd, options); 383 clientRuntime.log(msg + "\n"); executeImpl(); 385 } else { 386 if (!nonInteractive) { 387 String msg = NbBundle.getMessage(ExecutorSupport.class, "BK1005", new Date(), getDisplayName()); 388 clientRuntime.log(msg + "\n"); } 390 internalError = result.getError(); 391 group.fail(); 392 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, internalError); 393 } 395 } else { commandFinished((ClientRuntime.Result) e.getSource()); 397 if (cmd.hasFailed()) { 398 commandFailed = true; 399 group.fail(); 400 report(NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandFailed_Title"), 401 NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandFailed_Prompt"), 402 errorMessages, NotifyDescriptor.ERROR_MESSAGE); 403 } 404 if (warningMessages.size() > 0) { 405 report(NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandWarning_Title"), 406 NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandWarning_Prompt"), 407 warningMessages, NotifyDescriptor.WARNING_MESSAGE); 408 } 409 } 410 } 411 } finally { 412 if (terminated) { 413 cleanup(); 414 synchronized(this) { 415 finishedExecution = true; 416 notifyAll(); 417 } 418 419 Iterator it; 420 synchronized(taskListeners) { 421 it = new ArrayList(taskListeners).iterator(); 422 } 423 while (it.hasNext()) { 424 try { 425 TaskListener listener = (TaskListener) it.next(); 426 listener.taskFinished(task); 427 } catch (RuntimeException ex) { 428 ErrorManager.getDefault().notify(ex); 429 } 430 } 431 432 group.finished(clientRuntime, this); 433 } 434 } 435 } 436 437 protected void report(String title, String prompt, List <String > messages, int type) { 438 if (nonInteractive) return; 439 boolean emptyReport = true; 440 for (String message : messages) { 441 if (message != null && message.length() > 0) { 442 emptyReport = false; 443 break; 444 } 445 } 446 if (emptyReport) return; 447 CommandReport report = new CommandReport(prompt, messages); 448 JButton ok = new JButton(NbBundle.getMessage(ExecutorSupport.class, "MSG_CommandReport_OK")); 449 NotifyDescriptor descriptor = new NotifyDescriptor( 450 report, 451 title, 452 NotifyDescriptor.DEFAULT_OPTION, 453 type, 454 new Object [] { ok }, 455 ok); 456 DialogDisplayer.getDefault().notify(descriptor); 457 } 458 459 460 public void addTaskListener(TaskListener l) { 461 synchronized(taskListeners) { 462 taskListeners.add(l); 463 } 464 } 465 466 public void removeTaskListener(TaskListener l) { 467 synchronized(taskListeners) { 468 taskListeners.remove(l); 469 } 470 } 471 472 476 private boolean retryConnection(Throwable cause) { 477 478 Throwable initialCause = cause; 479 String cvsRoot = getCvsRoot(); 480 if (cvsRoot == null) return false; 481 482 final CVSRoot root; 483 try { 484 root = CVSRoot.parse(cvsRoot); 485 } catch (IllegalArgumentException ex) { 486 return false; 487 } 488 489 final RootWizard rootWizard = RootWizard.configureRoot(root.toString()); 490 JPanel panel = new JPanel(); 491 panel.setLayout(new BorderLayout()); 492 panel.setBorder(BorderFactory.createEmptyBorder(0,6,6,6)); 493 StringBuffer reason = new StringBuffer ("<ul>"); while (cause != null) { 495 try { 496 String msg = cause.getLocalizedMessage(); 497 if (msg == null) { 498 msg = cause.getClass().getName(); 499 } else { 500 msg = XMLUtil.toElementContent(msg); 501 } 502 reason.append("<li>" + msg + "</li>"); } catch (IOException ex) { 504 ErrorManager.getDefault().notify(ex); 505 } 506 cause = cause.getCause(); 507 } 508 reason.append("</ul>"); String msg = NbBundle.getMessage(ExecutorSupport.class, "BK0001", reason.toString(), cvsRoot); 510 JLabel label = new JLabel(msg); 511 int ex = Math.max((int) (cvsRoot.length() * 1.1), 50); 512 UIUtils.computePreferredSize(label, ex); 513 panel.add(label, BorderLayout.NORTH); 514 panel.add(rootWizard.getPanel(), BorderLayout.CENTER); 515 516 String okMsg = NbBundle.getMessage(ExecutorSupport.class, "CTL_Password_Action_Ok"); 517 final JButton ok = new JButton(okMsg); 518 ok.setEnabled(rootWizard.isValid()); 519 ok.getAccessibleContext().setAccessibleDescription(okMsg); 520 String cancelMsg = NbBundle.getMessage(ExecutorSupport.class, "CTL_Password_Action_Cancel"); 521 final JButton cancel = new JButton(cancelMsg); 522 cancel.getAccessibleContext().setAccessibleDescription(cancelMsg); 523 DialogDescriptor descriptor = new DialogDescriptor( 524 panel, 525 NbBundle.getMessage(ExecutorSupport.class, "BK0004", getDisplayName()), 526 true, 527 new Object [] { ok, cancel }, 528 ok, 529 DialogDescriptor.BOTTOM_ALIGN, 530 null, 531 new ActionListener () { 532 public void actionPerformed(ActionEvent e) { 533 } 534 }); 535 descriptor.setMessageType(DialogDescriptor.WARNING_MESSAGE); 536 descriptor.setClosingOptions(null); 537 rootWizard.addChangeListener(new ChangeListener () { 538 public void stateChanged(ChangeEvent e) { 539 ok.setEnabled(rootWizard.isValid()); 540 } 541 }); 542 543 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, initialCause); 544 Dialog dialog = DialogDisplayer.getDefault().createDialog(descriptor); 545 dialog.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(ExecutorSupport.class, "BK0005")); 546 dialog.setVisible(true); 547 548 boolean retry = false; 549 if (descriptor.getValue() == ok) { 550 rootWizard.commit(false); 551 retry = true; 552 } 553 return retry; 554 } 555 556 private String getCvsRoot() { 557 if (cmd.getGlobalOptions() != null && cmd.getGlobalOptions().getCVSRoot() != null) return cmd.getGlobalOptions().getCVSRoot(); 558 if (options != null && options.getCVSRoot() != null) return options.getCVSRoot(); 559 try { 560 return cvs.detectCvsRoot(cmd); 561 } catch (NotVersionedException e) { 562 } 563 return null; 564 } 565 566 protected abstract void commandFinished(ClientRuntime.Result result); 567 568 public void moduleExpanded(ModuleExpansionEvent e) { 569 } 570 571 582 protected static BasicCommand [] prepareBasicCommand(BasicCommand cmd) throws IOException { 583 String format = cmd.getDisplayName(); 584 File [] files = cmd.getFiles(); 585 if (files == null || files.length < 2) { 586 if (format != null) cmd.setDisplayName(MessageFormat.format(format, new Object [] { files == null ? "" : files[0].getName() })); return new BasicCommand [] { cmd }; 588 } 589 File [][] fileSets = splitFiles(files); 590 if (fileSets.length == 1) { 591 String nfiles = NbBundle.getMessage(ExecutorSupport.class, "MSG_ExecutorSupport_CommandFiles", Integer.toString(fileSets[0].length)); 592 if (format != null) cmd.setDisplayName(MessageFormat.format(format, new Object [] { nfiles })); 593 return new BasicCommand [] { cmd }; 594 } 595 BasicCommand [] commands = new BasicCommand[fileSets.length]; 596 CommandDuplicator cloner = CommandDuplicator.getDuplicator(cmd); 597 for (int i = 0; i < fileSets.length; i++) { 598 BasicCommand bc = (BasicCommand) cloner.duplicate(); 599 bc.setFiles(fileSets[i]); 600 commands[i] = bc; 601 String nfiles = NbBundle.getMessage(ExecutorSupport.class, "MSG_ExecutorSupport_CommandFiles", Integer.toString(fileSets[i].length)); 602 if (format != null) commands[i].setDisplayName(MessageFormat.format(format, new Object [] { nfiles })); 603 } 604 return commands; 605 } 606 607 615 protected static File [][] splitFiles(File [] files) throws IOException { 616 List ret = new ArrayList(); 617 File [][] aset = splitByCvsRoot(files); 618 for (int i = 0; i < aset.length; i++) { 619 File [] fileSet = aset[i]; 620 File [][] splitSet = splitByCommonParent(fileSet); 621 for (int j = 0; j < splitSet.length; j++) { 622 ret.add(splitSet[j]); 623 } 624 } 625 return (File [][]) ret.toArray(new File [ret.size()][]); 626 } 627 628 protected static File [][] splitByCvsRoot(File [] files) throws IOException { 632 Map fileBuckets = new HashMap(); 633 for (int i = 0; i < files.length; i++) { 634 File file = files[i]; 635 String root = Utils.getCVSRootFor(file); 636 Set bucket = (Set) fileBuckets.get(root); 637 if (bucket == null) { 638 bucket = new HashSet(); 639 fileBuckets.put(root, bucket); 640 } 641 bucket.add(file); 642 } 643 File [][] sets = new File [fileBuckets.size()][]; 644 int idx = 0; 645 for (Iterator i = fileBuckets.values().iterator(); i.hasNext();) { 646 Set bucket = (Set) i.next(); 647 sets[idx++] = (File []) bucket.toArray(new File [bucket.size()]); 648 } 649 return sets; 650 } 651 652 private static File [][] splitByCommonParent(File [] files) { 653 Map fileBuckets = new HashMap(); 654 for (int i = 0; i < files.length; i++) { 655 File file = files[i]; 656 File parent; 657 if (file.isDirectory()) { 658 parent = file; 659 } else { 660 parent = file.getParentFile(); 661 } 662 663 Set fileset = null; 664 File commonParent = null; 665 for (Iterator j = fileBuckets.keySet().iterator(); j.hasNext();) { 666 File key = (File ) j.next(); 667 commonParent = org.netbeans.modules.versioning.util.Utils.getCommonParent(parent, key); 668 if (commonParent != null) { 669 fileset = (Set) fileBuckets.get(key); 670 j.remove(); 671 break; 672 } 673 } 674 675 if (commonParent == null) { 676 fileset = new HashSet(1); 677 commonParent = parent; 678 } 679 fileset.add(file); 680 fileBuckets.put(commonParent, fileset); 681 } 682 683 File [][] sets = new File [fileBuckets.size()][]; 684 int idx = 0; 685 for (Iterator i = fileBuckets.values().iterator(); i.hasNext();) { 686 Set bucket = (Set) i.next(); 687 sets[idx++] = (File []) bucket.toArray(new File [bucket.size()]); 688 } 689 return sets; 690 } 691 692 698 public static boolean wait(ExecutorSupport[] executors) { 699 boolean success = true; 700 for (int i = 0; i < executors.length; i++) { 701 ExecutorSupport executor = executors[i]; 702 synchronized(executor) { 703 while (!executor.finishedExecution) { 704 try { 705 executor.wait(); 706 } catch (InterruptedException e) { 707 executor.getGroup().cancel(); 709 } 710 } 711 } 712 if (executor.isSuccessful() == false) { 713 success = false; 714 } 715 } 716 return success; 717 } 718 719 722 public void increaseDataCounter(long bytes) { 723 group.increaseDataCounter(bytes); 724 } 725 726 } 727 | Popular Tags |