001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS. 026 */ 027package org.opends.quicksetup.installer.ui; 028 029import org.forgerock.i18n.LocalizableMessage; 030import static org.opends.messages.QuickSetupMessages.*; 031 032import java.awt.Component; 033import java.awt.GridBagConstraints; 034import java.awt.GridBagLayout; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.awt.event.FocusEvent; 038import java.awt.event.FocusListener; 039import java.util.HashMap; 040 041import javax.swing.Box; 042import javax.swing.ButtonGroup; 043import javax.swing.JCheckBox; 044import javax.swing.JLabel; 045import javax.swing.JPanel; 046import javax.swing.JRadioButton; 047import javax.swing.event.DocumentEvent; 048import javax.swing.event.DocumentListener; 049import javax.swing.text.JTextComponent; 050 051import org.opends.quicksetup.ButtonName; 052import org.opends.quicksetup.UserData; 053import org.opends.quicksetup.event.ButtonEvent; 054import org.opends.quicksetup.installer.AuthenticationData; 055import org.opends.quicksetup.installer.DataReplicationOptions; 056import org.opends.quicksetup.ui.FieldName; 057import org.opends.quicksetup.ui.GuiApplication; 058import org.opends.quicksetup.ui.LabelFieldDescriptor; 059import org.opends.quicksetup.ui.QuickSetupStepPanel; 060import org.opends.quicksetup.ui.UIFactory; 061 062/** 063 * This class is used to display the replication options for the server 064 * that is being installed. 065 */ 066public class DataReplicationPanel extends QuickSetupStepPanel 067{ 068 private static final long serialVersionUID = -1721551487477733587L; 069 private Component lastFocusComponent; 070 private UserData defaultUserData; 071 072 private JRadioButton rbStandalone; 073 private JRadioButton rbReplicated; 074 private JCheckBox cbSecureReplication; 075 private JCheckBox cbTopologyExists; 076 private HashMap<FieldName, JLabel> hmLabels = new HashMap<>(); 077 private HashMap<FieldName, JTextComponent> hmFields = new HashMap<>(); 078 079 /** 080 * Constructor of the panel. 081 * @param application Application represented by this panel and used to 082 * initialize the fields of the panel. 083 */ 084 public DataReplicationPanel(GuiApplication application) 085 { 086 super(application); 087 this.defaultUserData = application.getUserData(); 088 populateComponentMaps(); 089 addDocumentListeners(); 090 addFocusListeners(); 091 addActionListeners(); 092 } 093 094 /** {@inheritDoc} */ 095 public Object getFieldValue(FieldName fieldName) 096 { 097 Object value = null; 098 099 if (fieldName == FieldName.REPLICATION_OPTIONS) 100 { 101 if (rbStandalone.isSelected()) 102 { 103 value = DataReplicationOptions.Type.STANDALONE; 104 } 105 else if (cbTopologyExists.isSelected()) 106 { 107 value = 108 DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY; 109 } 110 else 111 { 112 value = DataReplicationOptions.Type.FIRST_IN_TOPOLOGY; 113 } 114 } 115 else if (fieldName == FieldName.REPLICATION_SECURE) 116 { 117 value = Boolean.valueOf(cbSecureReplication.isSelected()); 118 } 119 else 120 { 121 JTextComponent field = getField(fieldName); 122 if (field != null) 123 { 124 value = field.getText(); 125 } 126 } 127 128 return value; 129 } 130 131 /** {@inheritDoc} */ 132 public void displayFieldInvalid(FieldName fieldName, boolean invalid) 133 { 134 JLabel label = getLabel(fieldName); 135 if (label != null) 136 { 137 UIFactory.TextStyle style; 138 139 if (invalid) 140 { 141 style = UIFactory.TextStyle.SECONDARY_FIELD_INVALID; 142 } else 143 { 144 style = UIFactory.TextStyle.SECONDARY_FIELD_VALID; 145 } 146 147 UIFactory.setTextStyle(label, style); 148 } 149 } 150 151 /** {@inheritDoc} */ 152 protected Component createInputPanel() 153 { 154 JPanel panel = new JPanel(new GridBagLayout()); 155 panel.setOpaque(false); 156 157 GridBagConstraints gbc = new GridBagConstraints(); 158 gbc.weightx = 1.0; 159 gbc.fill = GridBagConstraints.HORIZONTAL; 160 gbc.gridwidth = GridBagConstraints.REMAINDER; 161 gbc.insets = UIFactory.getEmptyInsets(); 162 panel.add(rbStandalone, gbc); 163 164 gbc.insets.top = UIFactory.TOP_INSET_RADIOBUTTON; 165 panel.add(rbReplicated, gbc); 166 167 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 168 gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE; 169 JPanel auxPanel = new JPanel(new GridBagLayout()); 170 auxPanel.setOpaque(false); 171 panel.add(auxPanel, gbc); 172 panel.add(cbTopologyExists, gbc); 173 gbc.insets = UIFactory.getEmptyInsets(); 174 gbc.gridwidth = 4; 175 gbc.weightx = 0.0; 176 gbc.insets.left = 0; 177 gbc.anchor = GridBagConstraints.WEST; 178 auxPanel.add(getLabel(FieldName.REPLICATION_PORT), gbc); 179 180 gbc.gridwidth--; 181 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 182 gbc.fill = GridBagConstraints.HORIZONTAL; 183 gbc.weightx = 0.0; 184 auxPanel.add(getField(FieldName.REPLICATION_PORT), gbc); 185 186 gbc.gridwidth = GridBagConstraints.RELATIVE; 187 gbc.fill = GridBagConstraints.HORIZONTAL; 188 gbc.weightx = 0.0; 189 auxPanel.add(cbSecureReplication, gbc); 190 191 gbc.gridwidth = GridBagConstraints.REMAINDER; 192 gbc.insets.left = 0; 193 gbc.weightx = 1.0; 194 gbc.fill = GridBagConstraints.HORIZONTAL; 195 auxPanel.add(Box.createHorizontalGlue(), gbc); 196 197 auxPanel = new JPanel(new GridBagLayout()); 198 auxPanel.setOpaque(false); 199 gbc.insets.left = 2 * UIFactory.LEFT_INSET_RADIO_SUBORDINATE; 200 panel.add(auxPanel, gbc); 201 202 // Add the server location widgets 203 FieldName[] fields = 204 { 205 FieldName.REMOTE_SERVER_HOST, 206 FieldName.REMOTE_SERVER_PORT, 207 FieldName.REMOTE_SERVER_DN, 208 FieldName.REMOTE_SERVER_PWD 209 }; 210 211 gbc.insets = UIFactory.getEmptyInsets(); 212 for (int i=0; i<fields.length; i++) 213 { 214 if (i != 0) 215 { 216 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 217 } 218 else 219 { 220 gbc.insets.top = 0; 221 } 222 gbc.gridwidth = GridBagConstraints.RELATIVE; 223 gbc.weightx = 0.0; 224 gbc.insets.left = 0; 225 gbc.anchor = GridBagConstraints.WEST; 226 auxPanel.add(getLabel(fields[i]), gbc); 227 228 JPanel aux2Panel = new JPanel(new GridBagLayout()); 229 aux2Panel.setOpaque(false); 230 231 if (fields[i] == FieldName.REMOTE_SERVER_PORT) 232 { 233 gbc.gridwidth = 3; 234 } 235 else 236 { 237 gbc.gridwidth = GridBagConstraints.RELATIVE; 238 } 239 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 240 gbc.fill = GridBagConstraints.HORIZONTAL; 241 gbc.weightx = 0.0; 242 aux2Panel.add(getField(fields[i]), gbc); 243 244 gbc.gridwidth = GridBagConstraints.REMAINDER; 245 gbc.insets.left = 0; 246 gbc.weightx = 1.0; 247 gbc.fill = GridBagConstraints.HORIZONTAL; 248 aux2Panel.add(Box.createHorizontalGlue(), gbc); 249 250 gbc.weightx = 1.0; 251 gbc.fill = GridBagConstraints.HORIZONTAL; 252 gbc.insets = UIFactory.getEmptyInsets(); 253 gbc.gridwidth = GridBagConstraints.REMAINDER; 254 auxPanel.add(aux2Panel, gbc); 255 } 256 257 addVerticalGlue(panel); 258 259 return panel; 260 } 261 262 /** {@inheritDoc} */ 263 protected LocalizableMessage getInstructions() 264 { 265 return INFO_DATA_REPLICATION_OPTIONS_PANEL_INSTRUCTIONS.get(); 266 } 267 268 /** {@inheritDoc} */ 269 protected LocalizableMessage getTitle() 270 { 271 return INFO_DATA_REPLICATION_OPTIONS_PANEL_TITLE.get(); 272 } 273 274 /** {@inheritDoc} */ 275 public void endDisplay() 276 { 277 if (lastFocusComponent != null) 278 { 279 lastFocusComponent.requestFocusInWindow(); 280 } 281 } 282 283 /** {@inheritDoc} */ 284 protected LocalizableMessage getTextForIcon(UIFactory.IconType iconType) 285 { 286 if (iconType == UIFactory.IconType.WAIT && 287 rbReplicated.isSelected() && cbTopologyExists.isSelected()) 288 { 289 return INFO_CONTACTING_SERVER_LABEL.get(); 290 } 291 else 292 { 293 return super.getTextForIcon(iconType); 294 } 295 } 296 297 /** 298 * Returns the default value for the provided field Name. 299 * @param fieldName the field name for which we want to get the default 300 * value. 301 * @return the default value for the provided field Name. 302 */ 303 private Object getDefaultValue(FieldName fieldName) 304 { 305 AuthenticationData auth = 306 defaultUserData.getReplicationOptions().getAuthenticationData(); 307 switch (fieldName) 308 { 309 case REPLICATION_PORT: 310 return defaultUserData.getReplicationOptions().getReplicationPort(); 311 case REMOTE_SERVER_DN: 312 return auth.getDn(); 313 case REMOTE_SERVER_PWD: 314 return auth.getPwd(); 315 case REMOTE_SERVER_HOST: 316 return auth.getHostName(); 317 case REMOTE_SERVER_PORT: 318 return auth.getPort(); 319 case REPLICATION_OPTIONS: 320 return defaultUserData.getReplicationOptions().getType(); 321 default: 322 throw new IllegalArgumentException("Unknown field name: " + fieldName); 323 } 324 } 325 326 /** 327 * Returns the default string value for the provided field Name. 328 * @param fieldName the field name for which we want to get the default 329 * string value. 330 * @return the default value for the provided field Name. 331 */ 332 private String getDefaultStringValue(FieldName fieldName) 333 { 334 Object v = getDefaultValue(fieldName); 335 if (v != null) 336 { 337 return String.valueOf(v); 338 } 339 return null; 340 } 341 342 /** 343 * Creates the components and populates the Maps with them. 344 */ 345 private void populateComponentMaps() 346 { 347 HashMap<FieldName, LabelFieldDescriptor> hm = new HashMap<>(); 348 349 hm.put(FieldName.REPLICATION_PORT, new LabelFieldDescriptor( 350 INFO_REPLICATION_PORT_LABEL.get(), 351 INFO_REPLICATION_PORT_TOOLTIP.get(), 352 LabelFieldDescriptor.FieldType.TEXTFIELD, 353 LabelFieldDescriptor.LabelType.SECONDARY, 354 UIFactory.PORT_FIELD_SIZE)); 355 356 hm.put(FieldName.REMOTE_SERVER_DN, new LabelFieldDescriptor( 357 INFO_REMOTE_SERVER_DN_LABEL.get(), 358 INFO_REMOTE_SERVER_DN_TOOLTIP.get(), 359 LabelFieldDescriptor.FieldType.TEXTFIELD, 360 LabelFieldDescriptor.LabelType.SECONDARY, UIFactory.DN_FIELD_SIZE)); 361 362 hm.put(FieldName.REMOTE_SERVER_PWD, new LabelFieldDescriptor( 363 INFO_REMOTE_SERVER_PWD_LABEL.get(), 364 INFO_REMOTE_SERVER_PWD_TOOLTIP.get(), 365 LabelFieldDescriptor.FieldType.PASSWORD, 366 LabelFieldDescriptor.LabelType.SECONDARY, 367 UIFactory.PASSWORD_FIELD_SIZE)); 368 369 hm.put(FieldName.REMOTE_SERVER_HOST, new LabelFieldDescriptor( 370 INFO_REMOTE_SERVER_HOST_LABEL.get(), 371 INFO_REMOTE_SERVER_HOST_TOOLTIP.get(), 372 LabelFieldDescriptor.FieldType.TEXTFIELD, 373 LabelFieldDescriptor.LabelType.SECONDARY, 374 UIFactory.HOST_FIELD_SIZE)); 375 376 hm.put(FieldName.REMOTE_SERVER_PORT, new LabelFieldDescriptor( 377 INFO_REMOTE_SERVER_PORT_LABEL.get(), 378 INFO_REMOTE_SERVER_PORT_TOOLTIP.get(), 379 LabelFieldDescriptor.FieldType.TEXTFIELD, 380 LabelFieldDescriptor.LabelType.SECONDARY, 381 UIFactory.PORT_FIELD_SIZE)); 382 383 for (FieldName fieldName : hm.keySet()) 384 { 385 LabelFieldDescriptor desc = hm.get(fieldName); 386 387 String defaultValue = getDefaultStringValue(fieldName); 388 JTextComponent field = UIFactory.makeJTextComponent(desc, defaultValue); 389 390 hmFields.put(fieldName, field); 391 392 JLabel l = UIFactory.makeJLabel(desc); 393 l.setLabelFor(field); 394 395 hmLabels.put(fieldName, l); 396 } 397 398 ButtonGroup buttonGroup = new ButtonGroup(); 399 rbStandalone = 400 UIFactory.makeJRadioButton(INFO_STANDALONE_SERVER_LABEL.get(), 401 INFO_STANDALONE_SERVER_TOOLTIP.get(), 402 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 403 rbStandalone.setOpaque(false); 404 rbReplicated = 405 UIFactory.makeJRadioButton(INFO_REPLICATED_SERVER_LABEL.get(), 406 INFO_REPLICATED_SERVER_TOOLTIP.get(), 407 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 408 rbReplicated.setOpaque(false); 409 buttonGroup.add(rbStandalone); 410 buttonGroup.add(rbReplicated); 411 412 DataReplicationOptions.Type type = 413 defaultUserData.getReplicationOptions().getType(); 414 cbTopologyExists = UIFactory.makeJCheckBox(INFO_TOPOLOGY_EXISTS_LABEL.get(), 415 INFO_TOPOLOGY_EXISTS_TOOLTIP.get(), 416 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 417 cbTopologyExists.setOpaque(false); 418 rbStandalone.setSelected(type == 419 DataReplicationOptions.Type.STANDALONE); 420 rbReplicated.setSelected(type != 421 DataReplicationOptions.Type.STANDALONE); 422 cbSecureReplication = UIFactory.makeJCheckBox( 423 INFO_SECURE_REPLICATION_LABEL.get(), 424 INFO_SECURE_REPLICATION_TOOLTIP.get(), 425 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 426 cbSecureReplication.setSelected( 427 defaultUserData.getReplicationOptions().useSecureReplication()); 428 cbTopologyExists.setSelected(type == 429 DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY); 430 checkEnablingState(); 431 } 432 433 /** 434 * Adds all the required document listeners to the fields. 435 */ 436 private void addDocumentListeners() 437 { 438 FieldName[] fields = { 439 FieldName.REMOTE_SERVER_DN, 440 FieldName.REMOTE_SERVER_PWD, 441 FieldName.REMOTE_SERVER_HOST, 442 FieldName.REMOTE_SERVER_PORT 443 }; 444 for (FieldName field : fields) { 445 JTextComponent tf = getField(field); 446 tf.getDocument().addDocumentListener(new DocumentListener() { 447 public void changedUpdate(DocumentEvent ev) { 448 if (!rbReplicated.isSelected()) { 449 rbReplicated.setSelected(true); 450 } 451 if (!cbTopologyExists.isSelected()) { 452 cbTopologyExists.setSelected(true); 453 } 454 } 455 456 public void insertUpdate(DocumentEvent ev) { 457 changedUpdate(ev); 458 } 459 460 public void removeUpdate(DocumentEvent ev) { 461 changedUpdate(ev); 462 } 463 }); 464 } 465 } 466 467 /** 468 * Adds the required focus listeners to the fields. 469 */ 470 private void addFocusListeners() 471 { 472 final FocusListener l = new FocusListener() 473 { 474 public void focusGained(FocusEvent e) 475 { 476 lastFocusComponent = e.getComponent(); 477 if (lastFocusComponent instanceof JTextComponent) 478 { 479 rbReplicated.setSelected(true); 480 if (lastFocusComponent != getField(FieldName.REPLICATION_PORT)) 481 { 482 cbTopologyExists.setSelected(true); 483 } 484 } 485 } 486 487 public void focusLost(FocusEvent e) 488 { 489 } 490 }; 491 492 for (JTextComponent tf : hmFields.values()) 493 { 494 tf.addFocusListener(l); 495 } 496 rbReplicated.addFocusListener(l); 497 rbStandalone.addFocusListener(l); 498 cbTopologyExists.addFocusListener(l); 499 cbSecureReplication.addFocusListener(l); 500 501 lastFocusComponent = rbStandalone; 502 } 503 504 /** 505 * Adds the required focus listeners to the fields. 506 */ 507 private void addActionListeners() 508 { 509 final ActionListener l = new ActionListener() 510 { 511 public void actionPerformed(ActionEvent ev) 512 { 513 checkEnablingState(); 514 ButtonEvent be = new ButtonEvent(ev.getSource(), 515 ButtonName.INPUT_PANEL_BUTTON); 516 notifyButtonListeners(be); 517 } 518 }; 519 rbReplicated.addActionListener(l); 520 rbStandalone.addActionListener(l); 521 cbTopologyExists.addActionListener(l); 522 cbTopologyExists.addActionListener(new ActionListener() 523 { 524 public void actionPerformed(ActionEvent ev) 525 { 526 if (cbTopologyExists.isSelected()) 527 { 528 rbReplicated.setSelected(true); 529 } 530 } 531 }); 532 } 533 534 /** 535 * Enables/disables the fields. 536 */ 537 private void checkEnablingState() 538 { 539 boolean enableFields = rbReplicated.isSelected() && 540 cbTopologyExists.isSelected(); 541 542 for (JTextComponent tf : hmFields.values()) 543 { 544 tf.setEnabled(enableFields); 545 } 546 547 for (JLabel l : hmLabels.values()) 548 { 549 l.setEnabled(enableFields); 550 } 551 552 cbTopologyExists.setEnabled(rbReplicated.isSelected()); 553 getLabel(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected()); 554 getField(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected()); 555 cbSecureReplication.setEnabled(rbReplicated.isSelected()); 556 } 557 558 /** 559 * Returns the label associated with the given field name. 560 * @param fieldName the field name for which we want to retrieve the JLabel. 561 * @return the label associated with the given field name. 562 */ 563 private JLabel getLabel(FieldName fieldName) 564 { 565 return hmLabels.get(fieldName); 566 } 567 568 /** 569 * Returns the JTextComponent associated with the given field name. 570 * @param fieldName the field name for which we want to retrieve the 571 * JTextComponent. 572 * @return the JTextComponent associated with the given field name. 573 */ 574 private JTextComponent getField(FieldName fieldName) 575 { 576 return hmFields.get(fieldName); 577 } 578}