1 19 20 package org.netbeans.modules.versioning.system.cvss.ui.wizards; 21 22 import org.openide.WizardDescriptor; 23 import org.openide.ErrorManager; 24 import org.openide.util.RequestProcessor; 25 import org.openide.util.NbBundle; 26 import org.openide.util.HelpCtx; 27 import org.netbeans.api.progress.ProgressHandle; 28 import org.netbeans.api.progress.ProgressHandleFactory; 29 import org.netbeans.api.options.OptionsDisplayer; 30 import org.netbeans.lib.cvsclient.connection.*; 31 import org.netbeans.lib.cvsclient.CVSRoot; 32 import org.netbeans.modules.versioning.system.cvss.CvsModuleConfig; 33 import org.netbeans.modules.versioning.system.cvss.SSHConnection; 34 import org.netbeans.modules.versioning.util.Utils; 35 36 import javax.swing.event.DocumentListener ; 37 import javax.swing.event.DocumentEvent ; 38 import javax.swing.*; 39 import javax.swing.text.JTextComponent ; 40 import javax.net.SocketFactory; 41 import java.awt.event.ActionListener ; 42 import java.awt.event.ActionEvent ; 43 import java.awt.*; 44 import java.util.*; 45 import java.net.Socket ; 46 import java.net.SocketAddress ; 47 import java.net.InetSocketAddress ; 48 import java.io.IOException ; 49 import java.lang.reflect.InvocationTargetException ; 50 51 58 public final class RepositoryStep extends AbstractStep implements WizardDescriptor.AsynchronousValidatingPanel, ActionListener , DocumentListener { 59 60 private static final String USE_INTERNAL_SSH = "repositoryStep.useInternalSSH"; 61 private static final String EXT_COMMAND = "repositoryStep.extCommand"; 62 private static final String RECENT_ROOTS = "repositoryStep.recentRoots"; 63 64 private RequestProcessor.Task updatePasswordTask; 65 private volatile boolean passwordExpected; 66 67 private ProgressHandle progress; 68 private JComponent progressComponent; 69 private JLabel progressLabel; 70 71 private volatile boolean internalDocumentChange; 72 private Thread backgroundValidationThread; 73 private RepositoryPanel repositoryPanel; 74 private String scrambledPassword; 75 private final String initialCvsRoot; 76 private String preferedCvsRoot; 77 78 79 82 public RepositoryStep() { 83 initialCvsRoot = null; 84 } 85 86 89 public RepositoryStep(String root) { 90 initialCvsRoot = root; 91 } 92 93 public HelpCtx getHelp() { 94 return new HelpCtx(RepositoryStep.class); 95 } 96 97 100 public void initPreferedCvsRoot(String root) { 101 preferedCvsRoot = root; 102 } 103 104 protected JComponent createComponent() { 105 repositoryPanel = new RepositoryPanel(); 106 107 109 repositoryPanel.extSshRadioButton.addActionListener(this); 110 repositoryPanel.internalSshRadioButton.addActionListener(this); 111 repositoryPanel.extCommandTextField.getDocument().addDocumentListener(this); 112 repositoryPanel.extPasswordField.getDocument().addDocumentListener(this); 113 repositoryPanel.passwordTextField.getDocument().addDocumentListener(this); 114 RequestProcessor requestProcessor = new RequestProcessor(); 115 updatePasswordTask = requestProcessor.create(new Runnable () { 116 public void run() { 117 String cvsRoot = selectedCvsRoot(); 118 String password = PasswordsFile.findPassword(cvsRoot); 119 if (password != null && passwordExpected) { 120 String fakePasswordWithProperLen = new String (password).substring(1); 121 scrambledPassword = password; 122 internalDocumentChange = true; 123 repositoryPanel.passwordTextField.setText(fakePasswordWithProperLen); 124 internalDocumentChange = false; 125 cancelPasswordUpdate(); 126 } 127 } 128 }); 129 130 132 Set recentRoots = new LinkedHashSet(); 133 if (preferedCvsRoot != null) { 134 recentRoots.add(preferedCvsRoot); 135 } 136 recentRoots.addAll(Utils.getStringList(CvsModuleConfig.getDefault().getPreferences(), RECENT_ROOTS)); 137 if (initialCvsRoot != null) { 138 recentRoots.add(initialCvsRoot); 140 } 141 Iterator cvsPassRoots = PasswordsFile.listRoots(":pserver:").iterator(); while (cvsPassRoots.hasNext()) { 143 String next = (String ) cvsPassRoots.next(); 144 if (recentRoots.contains(next) == false) { 145 recentRoots.add(next); 146 } 147 } 148 String user = System.getProperty("user.name", ""); if (user.length() > 0) user += "@"; recentRoots.add(":pserver:" + user); recentRoots.add(":ext:" + user); recentRoots.add(":fork:"); recentRoots.add(":local:"); 156 ComboBoxModel rootsModel = new DefaultComboBoxModel(new Vector(recentRoots)); 157 repositoryPanel.rootComboBox.setModel(rootsModel); 158 repositoryPanel.rootComboBox.addActionListener(this); 159 Component editor = repositoryPanel.rootComboBox.getEditor().getEditorComponent(); 160 JTextComponent textEditor = (JTextComponent ) editor; 161 if (recentRoots.size() == 0) { 162 textEditor.setText(":pserver:" + user); } else { 164 validateCvsRoot(); 165 CVSRoot root = getCVSRoot(); 166 schedulePasswordUpdate(); 167 } 168 textEditor.selectAll(); 169 textEditor.getDocument().addDocumentListener(this); 170 171 boolean useInternalSsh = CvsModuleConfig.getDefault().getPreferences().getBoolean(USE_INTERNAL_SSH, true); 172 repositoryPanel.internalSshRadioButton.setSelected(useInternalSsh); 173 repositoryPanel.extSshRadioButton.setSelected(!useInternalSsh); 174 175 String extCommand = CvsModuleConfig.getDefault().getPreferences().get(EXT_COMMAND, ""); 176 repositoryPanel.extCommandTextField.setText(extCommand); 177 178 repositoryPanel.proxyConfigurationButton.addActionListener(this); 179 repositoryPanel.editButton.addActionListener(this); 180 181 valid(); 182 onCvsRootChange(); 183 184 if (initialCvsRoot != null) { 185 boolean chooserVisible = false; 186 repositoryPanel.headerLabel.setVisible(chooserVisible); 187 repositoryPanel.rootsLabel.setVisible(chooserVisible); 188 repositoryPanel.rootComboBox.setVisible(chooserVisible); 189 repositoryPanel.descLabel.setVisible(chooserVisible); 190 repositoryPanel.editButton.setVisible(chooserVisible); 191 } 192 193 return repositoryPanel; 194 } 195 196 201 protected void validateBeforeNext() { 202 203 if (validateCvsRoot() == false) { 204 return; 205 } 206 final CVSRoot root = getCVSRoot(); 207 208 backgroundValidationThread = Thread.currentThread(); 209 210 final String invalidMsg[] = new String [1]; Runnable worker = new Runnable () { 212 213 private void fail(String msg) { 214 invalidMsg[0] = msg; 215 } 216 217 public void run() { 218 219 String host = root.getHostName(); 220 String userName = root.getUserName(); 221 int port = root.getPort(); 222 Socket sock = null; 223 Connection connection = null; 224 225 try { 226 if (root.isLocal()) { 227 LocalConnection lconnection = new LocalConnection(); 228 lconnection.setRepository(root.getRepository()); 229 lconnection.verify(); 230 } else { 231 invalid(null); 232 progress(NbBundle.getMessage(CheckoutWizard.class, "BK2011")); 233 SocketFactory factory = SocketFactory.getDefault(); 234 235 237 if (CVSRoot.METHOD_PSERVER.equals(root.getMethod())) { 238 port = port == 0 ? 2401 : port; 240 SocketAddress target = new InetSocketAddress (host, port); 241 sock = factory.createSocket(); 242 sock.connect(target, 5000); 243 sock.close(); 244 245 progress(NbBundle.getMessage(CheckoutWizard.class, "BK2010")); 247 PServerConnection pconnection = new PServerConnection(root, factory); 248 String password = getScrambledPassword(); 249 pconnection.setEncodedPassword(password); 250 pconnection.verify(); 251 } else if (CVSRoot.METHOD_EXT.equals(root.getMethod())) { 252 if (repositoryPanel.internalSshRadioButton.isSelected()) { 253 port = port == 0 ? 22 : port; String password = repositoryPanel.extPasswordField.getText(); 255 SSHConnection sshConnection = new SSHConnection(factory, host, port, userName, password); 256 sshConnection.setRepository(root.getRepository()); 257 sshConnection.verify(); 258 } else { 259 String command = repositoryPanel.extCommandTextField.getText(); 260 String userOption = ""; if ( userName != null) { 262 userOption = " -l " + userName; } 264 String cvs_server = System.getenv("CVS_SERVER") != null? 265 System.getenv("CVS_SERVER") + " server": "cvs server"; command += " " + host + userOption + " " + cvs_server; ExtConnection econnection = new ExtConnection(command); 268 econnection.setRepository(root.getRepository()); 269 econnection.verify(); 270 } 271 } else { 272 assert false : "Login check implemented only for pserver"; } 274 } 275 276 } catch (IOException e) { 277 ErrorManager err = ErrorManager.getDefault(); 278 err.annotate(e, org.openide.util.NbBundle.getMessage(RepositoryStep.class, "BK2019")); err.notify(ErrorManager.INFORMATIONAL, e); 280 String msg = NbBundle.getMessage(CheckoutWizard.class, "BK1001", host); 281 fail(msg); 282 } catch (AuthenticationException e) { 283 ErrorManager err = ErrorManager.getDefault(); 284 err.annotate(e, "Connection authentification verification failed."); err.notify(ErrorManager.INFORMATIONAL, e); 286 287 String msg; 289 if (e.getLocalizedMessage() != null && e.getLocalizedMessage().startsWith("<")) { msg = e.getLocalizedMessage(); 291 } else { 292 if (root.isLocal()) { 293 msg = NbBundle.getMessage(CheckoutWizard.class, "BK1004"); 294 } else { 295 msg = NbBundle.getMessage(CheckoutWizard.class, "BK1002"); 296 } 297 } 298 fail(msg); 299 } finally { 300 if (sock != null) { 301 try { 302 sock.close(); 303 } catch (IOException e) { 304 } 306 } 307 if (connection != null) { 308 try { 309 connection.close(); 310 } catch (IOException e) { 311 } 313 } 314 } 315 } 316 }; 317 318 Thread workerThread = new Thread (worker, "CVS I/O Probe "); workerThread.start(); 320 try { 321 workerThread.join(); 322 if (invalidMsg[0] == null) { 323 valid(); 324 storeValidValues(); 325 } else { 326 valid(invalidMsg[0]); 327 } 328 } catch (InterruptedException e) { 329 invalid(org.openide.util.NbBundle.getMessage(RepositoryStep.class, "BK2023")); 330 ErrorManager err = ErrorManager.getDefault(); 331 err.annotate(e, "Passing interrupt to possibly uninterruptible nested thread: " + workerThread); workerThread.interrupt(); 333 err.notify(ErrorManager.INFORMATIONAL, e); 334 } finally { 335 backgroundValidationThread = null; 336 SwingUtilities.invokeLater(new Runnable () { 337 public void run() { 338 validationDone(); 339 } 340 }); 341 } 342 343 } 344 345 private void progress(String message) { 346 if (progressLabel != null) { 347 progressLabel.setText(message); 348 } 349 } 350 351 private void validationDone() { 352 progress.finish(); 353 repositoryPanel.jPanel1.remove(progressComponent); 354 repositoryPanel.jPanel1.revalidate(); 355 repositoryPanel.jPanel1.repaint(); 356 editable(true); 357 } 358 359 private void editable(boolean editable) { 360 repositoryPanel.rootComboBox.setEditable(editable); 361 repositoryPanel.passwordTextField.setEditable(editable); 362 repositoryPanel.extCommandTextField.setEditable(editable); 363 repositoryPanel.extPasswordField.setEditable(editable); 364 365 repositoryPanel.proxyConfigurationButton.setEnabled(editable); 366 repositoryPanel.extREmemberPasswordCheckBox.setEnabled(editable); 367 repositoryPanel.internalSshRadioButton.setEnabled(editable); 368 repositoryPanel.extSshRadioButton.setEnabled(editable); 369 } 370 371 372 void storeValidValues() { 373 String root = selectedCvsRoot(); 374 CVSRoot cvsRoot = CVSRoot.parse(root); 375 if (root.startsWith(":pserver:")) { try { 377 381 PasswordsFile.storePassword(root, getScrambledPassword()); 382 } catch (IOException e) { 383 ErrorManager err = ErrorManager.getDefault(); 384 err.annotate(e, org.openide.util.NbBundle.getMessage(RepositoryStep.class, "BK2020")); 385 err.notify(e); 386 } 387 } else if (root.startsWith(":ext:")) { boolean internalSsh = repositoryPanel.internalSshRadioButton.isSelected(); 389 CvsModuleConfig.ExtSettings extSettings = new CvsModuleConfig.ExtSettings(); 390 extSettings.extUseInternalSsh = internalSsh; 391 extSettings.extPassword = repositoryPanel.extPasswordField.getText(); 392 extSettings.extRememberPassword = repositoryPanel.extREmemberPasswordCheckBox.isSelected(); 393 extSettings.extCommand = repositoryPanel.extCommandTextField.getText(); 394 CvsModuleConfig.getDefault().getPreferences().putBoolean(USE_INTERNAL_SSH, internalSsh); 395 CvsModuleConfig.getDefault().getPreferences().put(EXT_COMMAND, extSettings.extCommand); 396 CvsModuleConfig.getDefault().setExtSettingsFor(cvsRoot, extSettings); 397 } 398 399 Utils.insert(CvsModuleConfig.getDefault().getPreferences(), RECENT_ROOTS, root, 8); 400 } 401 402 406 private boolean validateCvsRoot() { 407 String cvsRoot = selectedCvsRoot(); 408 String errorMessage = null; 409 boolean supportedMethod = false; 410 if (cvsRoot != null) { 411 supportedMethod |= cvsRoot.startsWith(":pserver:"); supportedMethod |= cvsRoot.startsWith(":local:"); supportedMethod |= cvsRoot.startsWith(":fork:"); supportedMethod |= cvsRoot.startsWith(":ext:"); } 416 if (supportedMethod == false ) { 417 errorMessage = NbBundle.getMessage(CheckoutWizard.class, "BK1000"); 418 } else { 419 try { 420 CVSRoot.parse(cvsRoot); 421 } catch (IllegalArgumentException ex) { 422 errorMessage = org.openide.util.NbBundle.getMessage(RepositoryStep.class, "BK2021") + ex.getLocalizedMessage(); 423 } 424 } 425 if (errorMessage != null) { 426 invalid(errorMessage); 427 } 428 return errorMessage == null; 429 } 430 431 435 private void onCvsRootChange() { 436 if (validateCvsRoot()) { 437 valid(); 438 CVSRoot root = getCVSRoot(); 439 if (CVSRoot.METHOD_EXT.equals(root.getMethod())) { 440 if (CvsModuleConfig.getDefault().hasExtSettingsFor(root)) { 441 CvsModuleConfig.ExtSettings extSettings = CvsModuleConfig.getDefault().getExtSettingsFor(root); 442 repositoryPanel.internalSshRadioButton.setSelected(extSettings.extUseInternalSsh); 443 repositoryPanel.extPasswordField.setText(extSettings.extPassword); 444 repositoryPanel.extREmemberPasswordCheckBox.setSelected(extSettings.extRememberPassword); 445 repositoryPanel.extCommandTextField.setText(extSettings.extCommand); 446 } 447 } 448 repositoryPanel.extPasswordField.setEditable(root.getPassword() == null); 449 repositoryPanel.passwordTextField.setEditable(root.getPassword() == null); 450 if (root.getPassword() != null) { 451 if (CVSRoot.METHOD_EXT.equals(root.getMethod())) { 452 repositoryPanel.extPasswordField.setText(root.getPassword()); 453 } else if (CVSRoot.METHOD_PSERVER.equals(root.getMethod())) { 454 repositoryPanel.passwordTextField.setText(root.getPassword()); 455 } 456 } else { 457 schedulePasswordUpdate(); 458 } 459 } 460 updateVisibility(); 461 updateLabel(); 462 } 463 464 private void updateLabel() { 465 String cvsRoot = selectedCvsRoot(); 466 if (cvsRoot.startsWith(":pserver:")) { repositoryPanel.descLabel.setText("(:pserver:username@hostname:/repository_path)"); } else if (cvsRoot.startsWith(":local:")) { repositoryPanel.descLabel.setText("(:local:/repository_path)"); } else if (cvsRoot.startsWith(":fork:")) { repositoryPanel.descLabel.setText("(:fork:/repository_path)"); } else if (cvsRoot.startsWith(":ext:")) { repositoryPanel.descLabel.setText("(:ext:username@hostname:/repository_path)"); } else { 475 repositoryPanel.descLabel.setText(NbBundle.getMessage(CheckoutWizard.class, "BK1014")); 476 } 477 478 } 479 480 481 private void updateVisibility() { 482 String root = selectedCvsRoot(); 483 boolean showPserverFields = root.startsWith(":pserver:"); boolean showExtFields = root.startsWith(":ext:"); 486 repositoryPanel.passwordTextField.setVisible(showPserverFields); 487 repositoryPanel.pPaswordLabel.setVisible(showPserverFields); 488 489 repositoryPanel.internalSshRadioButton.setVisible(showExtFields); 490 repositoryPanel.extSshRadioButton.setVisible(showExtFields); 491 492 repositoryPanel.extPasswordLabel5.setVisible(showExtFields); 493 repositoryPanel.extPasswordField.setVisible(showExtFields); 494 repositoryPanel.extPasswordField.setEnabled(repositoryPanel.internalSshRadioButton.isSelected()); 495 repositoryPanel.extREmemberPasswordCheckBox.setVisible(showExtFields); 496 repositoryPanel.extREmemberPasswordCheckBox.setEnabled(repositoryPanel.internalSshRadioButton.isSelected()); 497 498 repositoryPanel.extCommandLabel.setVisible(showExtFields); 499 repositoryPanel.extCommandTextField.setVisible(showExtFields); 500 repositoryPanel.extCommandTextField.setEnabled(repositoryPanel.extSshRadioButton.isSelected()); 501 502 repositoryPanel.proxyConfigurationButton.setVisible(showPserverFields || showExtFields); 503 repositoryPanel.proxyConfigurationButton.setEnabled(!repositoryPanel.extSshRadioButton.isSelected()); 504 repositoryPanel.browseButton.setVisible(showExtFields); 505 repositoryPanel.browseButton.setEnabled(repositoryPanel.extSshRadioButton.isSelected()); 506 } 507 508 512 private String selectedCvsRoot() { 513 if (initialCvsRoot != null) { 514 return initialCvsRoot; 515 } 516 final String cvsRoot[] = new String [1]; 517 try { 518 Runnable awt = new Runnable () { 519 public void run() { 520 cvsRoot[0] = (String ) repositoryPanel.rootComboBox.getEditor().getItem(); 521 } 522 }; 523 if (SwingUtilities.isEventDispatchThread()) { 524 awt.run(); 525 } else { 526 SwingUtilities.invokeAndWait(awt); 527 } 528 String root = cvsRoot[0].trim(); 529 try { 530 return CVSRoot.parse(root).toString(); 531 } catch (Exception e) { 532 return root; 533 } 534 } catch (InterruptedException e) { 535 ErrorManager err = ErrorManager.getDefault(); 536 err.notify(e); 537 } catch (InvocationTargetException e) { 538 ErrorManager err = ErrorManager.getDefault(); 539 err.notify(e); 540 } 541 return null; 542 } 543 544 private CVSRoot getCVSRoot() { 545 try { 546 String root = selectedCvsRoot(); 547 return CVSRoot.parse(root); 548 } catch (IllegalArgumentException e) { 549 } 551 return null; 552 } 553 554 557 private void schedulePasswordUpdate() { 558 String root = selectedCvsRoot(); 559 if (root.startsWith(":pserver:")) { passwordExpected = true; 561 updatePasswordTask.schedule(10); 562 } 563 } 564 565 private void cancelPasswordUpdate() { 566 passwordExpected = false; 567 } 568 569 private void onPasswordChange() { 570 cancelPasswordUpdate(); 571 scrambledPassword = null; 572 if (validateCvsRoot()) { 573 valid(); 574 } 575 } 576 577 private void setValid() { 578 valid(); 579 } 580 581 private void onProxyConfiguration() { 582 OptionsDisplayer.getDefault().open("General"); 583 if (validateCvsRoot()) { 584 valid(); 585 } 586 } 587 588 private void editRoot() { 589 String root = selectedCvsRoot(); 590 root = RootWizard.editCvsRoot(root); 591 if (root != null) { 592 repositoryPanel.rootComboBox.setSelectedItem(root); 593 } 594 } 595 596 598 public void actionPerformed(ActionEvent e) { 599 if (repositoryPanel.proxyConfigurationButton == e.getSource()) { 600 onProxyConfiguration(); 601 } else if (repositoryPanel.rootComboBox == e.getSource()) { 602 onCvsRootChange(); 603 } else if (repositoryPanel.editButton == e.getSource()) { 604 editRoot(); 605 } else if (repositoryPanel.extSshRadioButton == e.getSource()) { 606 setValid(); 607 validateCvsRoot(); 608 updateVisibility(); 609 } else if (repositoryPanel.internalSshRadioButton == e.getSource()) { 610 setValid(); 611 validateCvsRoot(); 612 updateVisibility(); 613 } else { 614 assert false : "Unexpected event source: " + e.getSource(); } 616 } 617 618 public void changedUpdate(DocumentEvent e) { 619 } 620 621 public void insertUpdate(DocumentEvent e) { 622 textChanged(e); 623 } 624 625 public void removeUpdate(DocumentEvent e) { 626 textChanged(e); 627 } 628 629 private void textChanged(final DocumentEvent e) { 630 if (internalDocumentChange) return; 634 Runnable awt = new Runnable () { 635 public void run() { 636 if (e.getDocument() == repositoryPanel.passwordTextField.getDocument()) { 637 onPasswordChange(); 638 } else if (e.getDocument() == ((JTextComponent ) repositoryPanel.rootComboBox.getEditor().getEditorComponent()).getDocument()) { 639 onCvsRootChange(); 640 } else if (e.getDocument() == repositoryPanel.extPasswordField.getDocument()) { 641 setValid(); 642 validateCvsRoot(); 643 } else if (e.getDocument() == repositoryPanel.extCommandTextField.getDocument()) { 644 setValid(); 645 validateCvsRoot(); 646 } 647 } 648 }; 649 SwingUtilities.invokeLater(awt); 650 } 651 652 public void prepareValidation() { 653 progress = ProgressHandleFactory.createHandle(NbBundle.getMessage(CheckoutWizard.class, "BK2012")); 654 JComponent bar = ProgressHandleFactory.createProgressComponent(progress); 655 JButton stopButton = new JButton(org.openide.util.NbBundle.getMessage(RepositoryStep.class, "BK2022")); 656 stopButton.addActionListener(new ActionListener () { 657 public void actionPerformed(ActionEvent e) { 658 if (backgroundValidationThread != null) { 659 backgroundValidationThread.interrupt(); 660 } 661 } 662 }); 663 progressComponent = new JPanel(); 664 progressComponent.setLayout(new BorderLayout(6, 0)); 665 progressLabel = new JLabel(); 666 progressComponent.add(progressLabel, BorderLayout.NORTH); 667 progressComponent.add(bar, BorderLayout.CENTER); 668 progressComponent.add(stopButton, BorderLayout.LINE_END); 669 progress.start(); 670 repositoryPanel.jPanel1.setLayout(new BorderLayout()); 671 repositoryPanel.jPanel1.add(progressComponent, BorderLayout.SOUTH); 672 repositoryPanel.jPanel1.revalidate(); 673 674 editable(false); 675 } 676 677 private String getPassword() { 678 return new String (repositoryPanel.passwordTextField.getPassword()); 679 } 680 681 public String getCvsRoot() { 682 return selectedCvsRoot(); 683 } 684 685 public String getScrambledPassword() { 686 if (scrambledPassword == null) { 687 String plainPassword = getPassword(); 688 scrambledPassword = StandardScrambler.getInstance().scramble(plainPassword); 689 } 690 return scrambledPassword; 691 } 692 } 693 | Popular Tags |