1 19 20 package org.netbeans.modules.subversion.ui.repository; 21 22 import java.awt.BorderLayout ; 23 import java.awt.Component ; 24 import java.awt.Dialog ; 25 import java.awt.event.ActionEvent ; 26 import java.awt.event.ActionListener ; 27 import java.awt.event.FocusEvent ; 28 import java.awt.event.FocusListener ; 29 import java.awt.event.ItemEvent ; 30 import java.awt.event.ItemListener ; 31 import java.beans.PropertyChangeEvent ; 32 import java.beans.PropertyChangeListener ; 33 import java.lang.reflect.InvocationTargetException ; 34 import java.net.MalformedURLException ; 35 import java.text.MessageFormat ; 36 import java.util.ArrayList ; 37 import java.util.Iterator ; 38 import java.util.LinkedHashSet ; 39 import java.util.List ; 40 import java.util.Set ; 41 import java.util.Vector ; 42 import javax.swing.ComboBoxModel ; 43 import javax.swing.DefaultComboBoxModel ; 44 import javax.swing.SwingUtilities ; 45 import javax.swing.event.DocumentEvent ; 46 import javax.swing.event.DocumentListener ; 47 import javax.swing.text.JTextComponent ; 48 import org.netbeans.api.options.OptionsDisplayer; 49 import org.netbeans.modules.subversion.SvnModuleConfig; 50 import org.netbeans.modules.subversion.config.SvnConfigFiles; 51 import org.openide.DialogDescriptor; 52 import org.openide.DialogDisplayer; 53 import org.openide.ErrorManager; 54 import org.openide.util.HelpCtx; 55 import org.openide.util.NbBundle; 56 import org.tigris.subversion.svnclientadapter.SVNRevision; 57 import org.tigris.subversion.svnclientadapter.SVNUrl; 58 59 62 public class Repository implements ActionListener , DocumentListener , FocusListener , ItemListener { 63 64 public final static int FLAG_URL_EDITABLE = 2; 65 public final static int FLAG_URL_ENABLED = 4; 66 public final static int FLAG_ACCEPT_REVISION = 8; 67 public final static int FLAG_SHOW_REMOVE = 16; 68 public final static int FLAG_SHOW_HINTS = 32; 69 70 private final static String LOCAL_URL_HELP = "file:///repository_path[@REV]"; private final static String HTTP_URL_HELP = "http://hostname/repository_path[@REV]"; private final static String HTTPS_URL_HELP = "https://hostname/repository_path[@REV]"; private final static String SVN_URL_HELP = "svn://hostname/repository_path[@REV]"; private final static String SVN_SSH_URL_HELP = "svn+{0}://hostname/repository_path[@REV]"; 76 private RepositoryPanel repositoryPanel; 77 private boolean valid = true; 78 private List <PropertyChangeListener > listeners; 79 80 private RepositoryConnection editedRC; 81 82 public static final String PROP_VALID = "valid"; 84 private String message; 85 86 private int modeMask; 87 88 public Repository(String titleLabel) { 89 this(0, titleLabel); 90 } 91 92 public Repository(int modeMask, String titleLabel) { 93 94 this.modeMask = modeMask; 95 96 initPanel(); 97 refreshUrlHistory(); 98 99 repositoryPanel.titleLabel.setText(titleLabel); 100 101 repositoryPanel.urlComboBox.setEditable(isSet(FLAG_URL_EDITABLE)); 102 repositoryPanel.urlComboBox.setEnabled(isSet(FLAG_URL_ENABLED)); 103 repositoryPanel.tunnelHelpLabel.setVisible(isSet(FLAG_SHOW_HINTS)); 104 repositoryPanel.tipLabel.setVisible(isSet(FLAG_SHOW_HINTS)); 105 repositoryPanel.removeButton.setVisible(isSet(FLAG_SHOW_REMOVE)); 106 } 107 108 public void selectUrl(SVNUrl url, boolean force) { 109 DefaultComboBoxModel dcbm = (DefaultComboBoxModel ) repositoryPanel.urlComboBox.getModel(); 110 int idx = dcbm.getIndexOf(url.toString()); 111 if(idx > -1) { 112 repositoryPanel.urlComboBox.setSelectedItem(url.toString()); 113 } else if(force) { 114 RepositoryConnection rc = new RepositoryConnection(url.toString()); 115 repositoryPanel.urlComboBox.addItem(rc); 116 repositoryPanel.urlComboBox.setSelectedItem(rc); 117 } 118 } 119 120 public void actionPerformed(ActionEvent e) { 121 if(e.getSource()==repositoryPanel.proxySettingsButton) { 122 onProxyConfiguration(); 123 } else if(e.getSource()==repositoryPanel.removeButton) { 124 onRemoveClick(); 125 } 126 } 127 128 private void onProxyConfiguration() { 129 OptionsDisplayer.getDefault().open("General"); } 131 132 private void initPanel() { 133 repositoryPanel = new RepositoryPanel(); 134 135 repositoryPanel.proxySettingsButton.addActionListener(this); 136 repositoryPanel.removeButton.addActionListener(this); 137 138 repositoryPanel.urlComboBox.addActionListener(this); 139 getUrlComboEditor().getDocument().addDocumentListener(this); 140 141 repositoryPanel.userPasswordField.getDocument().addDocumentListener(this); 142 repositoryPanel.userPasswordField.addFocusListener(this); 143 144 repositoryPanel.userTextField.getDocument().addDocumentListener(this); 145 repositoryPanel.tunnelCommandTextField.getDocument().addDocumentListener(this); 146 147 repositoryPanel.urlComboBox.addItemListener(this); 148 149 onSelectedRepositoryChange(); 150 } 151 152 public void refreshUrlHistory() { 153 154 List <RepositoryConnection> recentUrls = SvnModuleConfig.getDefault().getRecentUrls(); 155 156 Set <RepositoryConnection> recentRoots = new LinkedHashSet <RepositoryConnection>(); 157 recentRoots.addAll(recentUrls); 158 159 if(repositoryPanel.urlComboBox.isEditable()) { 160 recentRoots.add(new RepositoryConnection("file:///")); recentRoots.add(new RepositoryConnection("http://")); recentRoots.add(new RepositoryConnection("https://")); recentRoots.add(new RepositoryConnection("svn://")); recentRoots.add(new RepositoryConnection("svn+ssh://")); }; 167 168 ComboBoxModel rootsModel = new RepositoryModel(new Vector <RepositoryConnection>(recentRoots)); 169 repositoryPanel.urlComboBox.setModel(rootsModel); 170 171 if (recentRoots.size() > 0 ) { 172 repositoryPanel.urlComboBox.setSelectedIndex(0); 173 refresh(getSelectedRC()); 174 } 175 176 if(repositoryPanel.urlComboBox.isEditable()) { 177 JTextComponent textEditor = getUrlComboEditor(); 178 textEditor.selectAll(); 179 } 180 } 181 182 public void storeRecentUrls() { 183 SvnModuleConfig.getDefault().setRecentUrls(getRecentUrls()); 184 } 185 186 private List <RepositoryConnection> getRecentUrls() { 187 ComboBoxModel model = repositoryPanel.urlComboBox.getModel(); 188 List <RepositoryConnection> ret = new ArrayList <RepositoryConnection>(model.getSize()); 189 for (int i = 0; i < model.getSize(); i++) { 190 ret.add((RepositoryConnection)model.getElementAt(i)); 191 } 192 return ret; 193 } 194 195 private JTextComponent getUrlComboEditor() { 196 Component editor = repositoryPanel.urlComboBox.getEditor().getEditorComponent(); 197 JTextComponent textEditor = (JTextComponent ) editor; 198 return textEditor; 199 } 200 201 public void setEditable(boolean editable) { 202 repositoryPanel.urlComboBox.setEditable(editable); 203 repositoryPanel.userPasswordField.setEditable(editable); 204 repositoryPanel.userTextField.setEditable(editable); 205 repositoryPanel.proxySettingsButton.setEnabled(editable); 206 } 207 208 public void storeConfigValues() { 209 RepositoryConnection rc = getSelectedRC(); 210 if(rc==null) { 211 return; } 213 214 try { 215 SVNUrl repositoryUrl = rc.getSvnUrl(); 216 if(repositoryUrl.getProtocol().startsWith("svn+")) { 217 SvnConfigFiles.getInstance().setExternalCommand(getTunnelName(repositoryUrl.getProtocol()), repositoryPanel.tunnelCommandTextField.getText()); 218 } 219 } catch (MalformedURLException mue) { 220 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, mue); 222 } 223 224 } 225 226 public void insertUpdate(DocumentEvent e) { 227 textChanged(e); 228 } 229 230 public void removeUpdate(DocumentEvent e) { 231 textChanged(e); 232 } 233 234 public void changedUpdate(DocumentEvent e) { } 235 236 private void textChanged(final DocumentEvent e) { 237 Runnable awt = new Runnable () { 241 public void run() { 242 if (e.getDocument() == repositoryPanel.userTextField.getDocument()) { 243 onUsernameChange(); 244 } else if (e.getDocument() == repositoryPanel.userPasswordField.getDocument()) { 245 onPasswordChange(); 246 } else if (e.getDocument() == ((JTextComponent ) repositoryPanel.urlComboBox.getEditor().getEditorComponent()).getDocument()) { 247 onSelectedRepositoryChange(); 248 } else if (e.getDocument() == (repositoryPanel.tunnelCommandTextField.getDocument())) { 249 onTunnelCommandChange(); 250 } 251 validateSvnUrl(); 252 } 253 }; 254 SwingUtilities.invokeLater(awt); 255 } 256 257 260 private void validateSvnUrl() { 261 boolean valid = true; 262 263 RepositoryConnection rc = null; 264 try { 265 rc = getSelectedRC(); 266 rc.getSvnUrl(); 268 if(!isSet(FLAG_ACCEPT_REVISION) && !rc.getSvnRevision().equals(SVNRevision.HEAD)) 269 { 270 message = NbBundle.getMessage(Repository.class, "MSG_Repository_OnlyHEADRevision"); 271 valid = false; 272 } else { 273 rc.getSvnRevision(); 275 } 276 } catch (Exception ex) { 277 message = ex.getLocalizedMessage(); 278 valid = false; 279 } 280 281 if(valid) { 282 valid = rc != null && !rc.getUrl().equals(""); 283 if(rc.getUrl().startsWith("svn+") && repositoryPanel.tunnelCommandTextField.getText().trim().equals("")) { 284 valid = false; 285 } 286 } 287 288 setValid(valid, message); 289 repositoryPanel.proxySettingsButton.setEnabled(valid); 290 repositoryPanel.userPasswordField.setEnabled(valid); 291 repositoryPanel.userTextField.setEnabled(valid); 292 293 repositoryPanel.removeButton.setEnabled(rc != null && rc.getUrl().length() > 0); 294 } 295 296 299 private void onSelectedRepositoryChange() { 300 setValid(true, ""); String urlString = ""; try { 303 urlString = getUrlString(); 304 } catch (InterruptedException ex) { 305 return; } 307 308 if(urlString != null) { 309 310 RepositoryConnection editedrc = getEditedRC(); 311 editedrc.setUrl(urlString); 312 313 DefaultComboBoxModel dcbm = (DefaultComboBoxModel ) repositoryPanel.urlComboBox.getModel(); 314 int idx = dcbm.getIndexOf(editedrc); 315 if(idx > -1) { 316 refresh((RepositoryConnection)dcbm.getElementAt(idx)); 318 } 319 if(urlString.startsWith("svn+")) { 320 String tunnelName = getTunnelName(urlString).trim(); 321 if( repositoryPanel.tunnelCommandTextField.getText().trim().equals("") && 322 tunnelName != null && 323 !tunnelName.equals("") ) 324 { 325 repositoryPanel.tunnelCommandTextField.setText(SvnConfigFiles.getInstance().getExternalCommand(tunnelName)); 326 } 327 } 328 329 editedrc.setUsername(repositoryPanel.userTextField.getText()); 330 editedrc.setPassword(new String (repositoryPanel.userPasswordField.getPassword())); 331 editedrc.setExternalCommand(repositoryPanel.tunnelCommandTextField.getText()); 332 } 333 message = ""; updateVisibility(); 335 } 336 337 private RepositoryConnection getEditedRC() { 338 if(editedRC == null) { 339 editedRC = new RepositoryConnection(""); 340 } 341 return editedRC; 342 } 343 344 345 private void updateVisibility() { 346 String selectedUrlString; 347 try { 348 selectedUrlString = getUrlString(); 349 } catch (InterruptedException ex) { 350 return; 351 } 352 boolean authFields = false; 353 boolean proxyFields = false; 354 boolean sshFields = false; 355 if(selectedUrlString.startsWith("http:")) { repositoryPanel.tipLabel.setText(HTTP_URL_HELP); 357 authFields = true; 358 proxyFields = true; 359 } else if(selectedUrlString.startsWith("https:")) { repositoryPanel.tipLabel.setText(HTTPS_URL_HELP); 361 authFields = true; 362 proxyFields = true; 363 } else if(selectedUrlString.startsWith("svn:")) { repositoryPanel.tipLabel.setText(SVN_URL_HELP); 365 authFields = true; 366 proxyFields = true; 367 } else if(selectedUrlString.startsWith("svn+")) { repositoryPanel.tipLabel.setText(getSVNTunnelTip(selectedUrlString)); 369 sshFields = true; 370 } else if(selectedUrlString.startsWith("file:")) { repositoryPanel.tipLabel.setText(LOCAL_URL_HELP); 372 } else { 373 repositoryPanel.tipLabel.setText(NbBundle.getMessage(Repository.class, "MSG_Repository_Url_Help", new Object [] { LOCAL_URL_HELP, HTTP_URL_HELP, HTTPS_URL_HELP, SVN_URL_HELP, SVN_SSH_URL_HELP 375 })); 376 } 377 378 repositoryPanel.userPasswordField.setVisible(authFields); 379 repositoryPanel.passwordLabel.setVisible(authFields); 380 repositoryPanel.userTextField.setVisible(authFields); 381 repositoryPanel.leaveBlankLabel.setVisible(authFields); 382 repositoryPanel.userLabel.setVisible(authFields); 383 repositoryPanel.proxySettingsButton.setVisible(proxyFields); 384 repositoryPanel.tunnelCommandTextField.setVisible(sshFields); 385 repositoryPanel.tunnelCommandLabel.setVisible(sshFields); 386 repositoryPanel.tunnelLabel.setVisible(sshFields); 387 repositoryPanel.tunnelHelpLabel.setVisible(sshFields); 388 389 } 390 391 private String getSVNTunnelTip(String urlString) { 392 String tunnelName = getTunnelName(urlString); 393 return MessageFormat.format(SVN_SSH_URL_HELP, tunnelName).trim(); 394 } 395 396 397 398 private String getTunnelName(String urlString) { 399 int idx = urlString.indexOf(":", 4); 400 if(idx < 0) { 401 idx = urlString.length(); 402 } 403 return urlString.substring(4, idx); 404 } 405 406 410 private String getUrlString() throws InterruptedException { 411 if(!repositoryPanel.urlComboBox.isEditable()) { 412 Object selection = repositoryPanel.urlComboBox.getSelectedItem(); 413 if(selection != null) { 414 return selection.toString().trim(); 415 } 416 return ""; 417 } else { 418 final String [] svnUrl = new String [1]; 419 try { 420 Runnable awt = new Runnable () { 421 public void run() { 422 svnUrl[0] = (String ) repositoryPanel.urlComboBox.getEditor().getItem().toString().trim(); 423 } 424 }; 425 if (SwingUtilities.isEventDispatchThread()) { 426 awt.run(); 427 } else { 428 SwingUtilities.invokeAndWait(awt); 429 } 430 return svnUrl[0].trim(); 431 } catch (InvocationTargetException e) { 432 ErrorManager err = ErrorManager.getDefault(); 433 err.notify(e); 434 } 435 return null; 436 } 437 } 438 439 public RepositoryConnection getSelectedRC() { 440 String urlString; 441 try { 442 urlString = getUrlString(); 443 } 444 catch (InterruptedException ex) { 445 ErrorManager.getDefault().notify(ex); 447 return null; 448 }; 449 450 DefaultComboBoxModel dcbm = (DefaultComboBoxModel ) repositoryPanel.urlComboBox.getModel(); 451 int idx = dcbm.getIndexOf(urlString); 452 453 if(idx > -1) { 454 return (RepositoryConnection) dcbm.getElementAt(idx); 455 } 456 return getEditedRC(); 457 } 458 459 private void onUsernameChange() { 460 RepositoryConnection rc = getSelectedRC(); 461 if (rc != null) { 462 rc.setUsername(repositoryPanel.userTextField.getText()); 463 } 464 setValid(true, ""); 465 } 466 467 private void onPasswordChange() { 468 RepositoryConnection rc = getSelectedRC(); 469 if (rc != null) { 470 rc.setPassword(new String (repositoryPanel.userPasswordField.getPassword())); 471 } 472 setValid(true, ""); 473 } 474 475 private void onTunnelCommandChange() { 476 RepositoryConnection rc = getSelectedRC(); 477 if (rc != null) { 478 rc.setExternalCommand(repositoryPanel.tunnelCommandTextField.getText()); 479 } 480 } 481 482 private void onRemoveClick() { 483 RepositoryConnection rc = getSelectedRC(); 484 if (rc != null) { 485 remove(rc); 486 } 487 } 488 489 public RepositoryPanel getPanel() { 490 return repositoryPanel; 491 } 492 493 public boolean isValid() { 494 return valid; 495 } 496 497 private void setValid(boolean valid, String message) { 498 boolean oldValue = this.valid; 499 this.message = message; 501 this.valid = valid; 502 fireValidPropertyChanged(oldValue, valid); 503 } 504 505 private void fireValidPropertyChanged(boolean oldValue, boolean valid) { 506 if(listeners==null) { 507 return; 508 } 509 for (Iterator it = listeners.iterator(); it.hasNext();) { 510 PropertyChangeListener l = (PropertyChangeListener ) it.next(); 511 l.propertyChange(new PropertyChangeEvent (this, PROP_VALID, new Boolean (oldValue), new Boolean (valid))); 512 } 513 } 514 515 public void addPropertyChangeListener(PropertyChangeListener l) { 516 if(listeners==null) { 517 listeners = new ArrayList <PropertyChangeListener >(); 518 } 519 listeners.add(l); 520 } 521 522 public void removePropertyChangeListener(PropertyChangeListener l) { 523 if(listeners==null) { 524 return; 525 } 526 listeners.remove(l); 527 } 528 529 public String getMessage() { 530 return message; 531 } 532 533 public void focusGained(FocusEvent focusEvent) { 534 if(focusEvent.getSource()==repositoryPanel.userPasswordField) { 535 repositoryPanel.userPasswordField.selectAll(); 536 } 537 } 538 539 public void focusLost(FocusEvent focusEvent) { 540 } 542 543 public void remove(RepositoryConnection toRemove) { 544 RepositoryModel model = (RepositoryModel) repositoryPanel.urlComboBox.getModel(); 545 model.removeElement(toRemove); 546 } 547 548 public void itemStateChanged(ItemEvent evt) { 549 if(evt.getStateChange() == ItemEvent.SELECTED) { 550 RepositoryConnection rc = (RepositoryConnection) evt.getItem(); 551 refresh(rc); 552 updateVisibility(); 553 editedRC = new RepositoryConnection(rc); 554 } 555 } 556 557 private void refresh(RepositoryConnection rc) { 558 repositoryPanel.userTextField.setText(rc.getUsername()); 559 repositoryPanel.userPasswordField.setText(rc.getPassword()); 560 repositoryPanel.tunnelCommandTextField.setText(rc.getExternalCommand()); 561 } 562 563 public boolean show(String title, HelpCtx helpCtx) { 564 RepositoryDialogPanel corectPanel = new RepositoryDialogPanel(); 565 corectPanel.panel.setLayout(new BorderLayout ()); 566 corectPanel.panel.add(getPanel(), BorderLayout.NORTH); 567 DialogDescriptor dialogDescriptor = new DialogDescriptor(corectPanel, title); showDialog(dialogDescriptor, helpCtx); 569 return dialogDescriptor.getValue() == DialogDescriptor.OK_OPTION; 570 } 571 572 public Object show(String title, HelpCtx helpCtx, Object [] options) { 573 RepositoryDialogPanel corectPanel = new RepositoryDialogPanel(); 574 corectPanel.panel.setLayout(new BorderLayout ()); 575 corectPanel.panel.add(getPanel(), BorderLayout.NORTH); 576 DialogDescriptor dialogDescriptor = new DialogDescriptor(corectPanel, title); if(options!= null) { 578 dialogDescriptor.setOptions(options); } 580 showDialog(dialogDescriptor, helpCtx); 581 return dialogDescriptor.getValue(); 582 } 583 584 private void showDialog(DialogDescriptor dialogDescriptor, HelpCtx helpCtx) { 585 dialogDescriptor.setModal(true); 586 dialogDescriptor.setHelpCtx(helpCtx); 587 588 Dialog dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor); 589 dialog.setVisible(true); 590 } 591 592 private boolean isSet(int flag) { 593 return (modeMask & flag) != 0; 594 } 595 596 public class RepositoryModel extends DefaultComboBoxModel { 597 598 public RepositoryModel(Vector v) { 599 super(v); 600 } 601 602 public void setSelectedItem(Object obj) { 603 if(obj instanceof String ) { 604 int idx = getIndexOf(obj); 605 if(idx > -1) { 606 obj = getElementAt(idx); 607 } else { 608 obj = createNewRepositoryConnection((String )obj); 609 } 610 } 611 super.setSelectedItem(obj); 612 } 613 614 public int getIndexOf(Object obj) { 615 if(obj instanceof String ) { 616 obj = createNewRepositoryConnection((String )obj); 617 } 618 return super.getIndexOf(obj); 619 } 620 621 public void addElement(Object obj) { 622 if(obj instanceof String ) { 623 obj = createNewRepositoryConnection((String )obj); 624 } 625 super.addElement(obj); 626 } 627 628 public void insertElementAt(Object obj,int index) { 629 if(obj instanceof String ) { 630 String str = (String ) obj; 631 RepositoryConnection rc = null; 632 try { 633 rc = (RepositoryConnection) getElementAt(index); 634 } catch (ArrayIndexOutOfBoundsException e) { 635 } 636 if(rc != null) { 637 rc.setUrl(str); 638 obj = rc; 639 } 640 obj = createNewRepositoryConnection(str); 641 } 642 super.insertElementAt(obj, index); 643 } 644 645 public void removeElement(Object obj) { 646 int index = getIndexOf(obj); 647 if ( index != -1 ) { 648 removeElementAt(index); 649 } 650 } 651 652 private RepositoryConnection createNewRepositoryConnection(String url) { 653 editedRC.setUrl(url); 654 return new RepositoryConnection(editedRC); 655 } 656 } 657 } 658 | Popular Tags |