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