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-2016 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 @Override 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 @Override 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 @Override 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 @Override 253 protected LocalizableMessage getInstructions() 254 { 255 return INFO_DATA_REPLICATION_OPTIONS_PANEL_INSTRUCTIONS.get(); 256 } 257 258 @Override 259 protected LocalizableMessage getTitle() 260 { 261 return INFO_DATA_REPLICATION_OPTIONS_PANEL_TITLE.get(); 262 } 263 264 @Override 265 public void endDisplay() 266 { 267 if (lastFocusComponent != null) 268 { 269 lastFocusComponent.requestFocusInWindow(); 270 } 271 } 272 273 @Override 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.getHostPort().getHost(); 307 case REMOTE_SERVER_PORT: 308 return auth.getHostPort().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 /** Creates the components and populates the Maps with them. */ 333 private void populateComponentMaps() 334 { 335 HashMap<FieldName, LabelFieldDescriptor> hm = new HashMap<>(); 336 337 hm.put(FieldName.REPLICATION_PORT, new LabelFieldDescriptor( 338 INFO_REPLICATION_PORT_LABEL.get(), 339 INFO_REPLICATION_PORT_TOOLTIP.get(), 340 LabelFieldDescriptor.FieldType.TEXTFIELD, 341 LabelFieldDescriptor.LabelType.SECONDARY, 342 UIFactory.PORT_FIELD_SIZE)); 343 344 hm.put(FieldName.REMOTE_SERVER_DN, new LabelFieldDescriptor( 345 INFO_REMOTE_SERVER_DN_LABEL.get(), 346 INFO_REMOTE_SERVER_DN_TOOLTIP.get(), 347 LabelFieldDescriptor.FieldType.TEXTFIELD, 348 LabelFieldDescriptor.LabelType.SECONDARY, UIFactory.DN_FIELD_SIZE)); 349 350 hm.put(FieldName.REMOTE_SERVER_PWD, new LabelFieldDescriptor( 351 INFO_REMOTE_SERVER_PWD_LABEL.get(), 352 INFO_REMOTE_SERVER_PWD_TOOLTIP.get(), 353 LabelFieldDescriptor.FieldType.PASSWORD, 354 LabelFieldDescriptor.LabelType.SECONDARY, 355 UIFactory.PASSWORD_FIELD_SIZE)); 356 357 hm.put(FieldName.REMOTE_SERVER_HOST, new LabelFieldDescriptor( 358 INFO_REMOTE_SERVER_HOST_LABEL.get(), 359 INFO_REMOTE_SERVER_HOST_TOOLTIP.get(), 360 LabelFieldDescriptor.FieldType.TEXTFIELD, 361 LabelFieldDescriptor.LabelType.SECONDARY, 362 UIFactory.HOST_FIELD_SIZE)); 363 364 hm.put(FieldName.REMOTE_SERVER_PORT, new LabelFieldDescriptor( 365 INFO_REMOTE_SERVER_PORT_LABEL.get(), 366 INFO_REMOTE_SERVER_PORT_TOOLTIP.get(), 367 LabelFieldDescriptor.FieldType.TEXTFIELD, 368 LabelFieldDescriptor.LabelType.SECONDARY, 369 UIFactory.PORT_FIELD_SIZE)); 370 371 for (FieldName fieldName : hm.keySet()) 372 { 373 LabelFieldDescriptor desc = hm.get(fieldName); 374 375 String defaultValue = getDefaultStringValue(fieldName); 376 JTextComponent field = UIFactory.makeJTextComponent(desc, defaultValue); 377 378 hmFields.put(fieldName, field); 379 380 JLabel l = UIFactory.makeJLabel(desc); 381 l.setLabelFor(field); 382 383 hmLabels.put(fieldName, l); 384 } 385 386 ButtonGroup buttonGroup = new ButtonGroup(); 387 rbStandalone = 388 UIFactory.makeJRadioButton(INFO_STANDALONE_SERVER_LABEL.get(), 389 INFO_STANDALONE_SERVER_TOOLTIP.get(), 390 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 391 rbStandalone.setOpaque(false); 392 rbReplicated = 393 UIFactory.makeJRadioButton(INFO_REPLICATED_SERVER_LABEL.get(), 394 INFO_REPLICATED_SERVER_TOOLTIP.get(), 395 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 396 rbReplicated.setOpaque(false); 397 buttonGroup.add(rbStandalone); 398 buttonGroup.add(rbReplicated); 399 400 DataReplicationOptions.Type type = 401 defaultUserData.getReplicationOptions().getType(); 402 cbTopologyExists = UIFactory.makeJCheckBox(INFO_TOPOLOGY_EXISTS_LABEL.get(), 403 INFO_TOPOLOGY_EXISTS_TOOLTIP.get(), 404 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 405 cbTopologyExists.setOpaque(false); 406 rbStandalone.setSelected(type == 407 DataReplicationOptions.Type.STANDALONE); 408 rbReplicated.setSelected(type != 409 DataReplicationOptions.Type.STANDALONE); 410 cbSecureReplication = UIFactory.makeJCheckBox( 411 INFO_SECURE_REPLICATION_LABEL.get(), 412 INFO_SECURE_REPLICATION_TOOLTIP.get(), 413 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 414 cbSecureReplication.setSelected( 415 defaultUserData.getReplicationOptions().useSecureReplication()); 416 cbTopologyExists.setSelected(type == 417 DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY); 418 checkEnablingState(); 419 } 420 421 /** Adds all the required document listeners to the fields. */ 422 private void addDocumentListeners() 423 { 424 FieldName[] fields = { 425 FieldName.REMOTE_SERVER_DN, 426 FieldName.REMOTE_SERVER_PWD, 427 FieldName.REMOTE_SERVER_HOST, 428 FieldName.REMOTE_SERVER_PORT 429 }; 430 for (FieldName field : fields) { 431 JTextComponent tf = getField(field); 432 tf.getDocument().addDocumentListener(new DocumentListener() { 433 @Override 434 public void changedUpdate(DocumentEvent ev) { 435 if (!rbReplicated.isSelected()) { 436 rbReplicated.setSelected(true); 437 } 438 if (!cbTopologyExists.isSelected()) { 439 cbTopologyExists.setSelected(true); 440 } 441 } 442 443 @Override 444 public void insertUpdate(DocumentEvent ev) { 445 changedUpdate(ev); 446 } 447 448 @Override 449 public void removeUpdate(DocumentEvent ev) { 450 changedUpdate(ev); 451 } 452 }); 453 } 454 } 455 456 /** Adds the required focus listeners to the fields. */ 457 private void addFocusListeners() 458 { 459 final FocusListener l = new FocusListener() 460 { 461 @Override 462 public void focusGained(FocusEvent e) 463 { 464 lastFocusComponent = e.getComponent(); 465 if (lastFocusComponent instanceof JTextComponent) 466 { 467 rbReplicated.setSelected(true); 468 if (lastFocusComponent != getField(FieldName.REPLICATION_PORT)) 469 { 470 cbTopologyExists.setSelected(true); 471 } 472 } 473 } 474 475 @Override 476 public void focusLost(FocusEvent e) 477 { 478 } 479 }; 480 481 for (JTextComponent tf : hmFields.values()) 482 { 483 tf.addFocusListener(l); 484 } 485 rbReplicated.addFocusListener(l); 486 rbStandalone.addFocusListener(l); 487 cbTopologyExists.addFocusListener(l); 488 cbSecureReplication.addFocusListener(l); 489 490 lastFocusComponent = rbStandalone; 491 } 492 493 /** Adds the required focus listeners to the fields. */ 494 private void addActionListeners() 495 { 496 final ActionListener l = new ActionListener() 497 { 498 @Override 499 public void actionPerformed(ActionEvent ev) 500 { 501 checkEnablingState(); 502 ButtonEvent be = new ButtonEvent(ev.getSource(), 503 ButtonName.INPUT_PANEL_BUTTON); 504 notifyButtonListeners(be); 505 } 506 }; 507 rbReplicated.addActionListener(l); 508 rbStandalone.addActionListener(l); 509 cbTopologyExists.addActionListener(l); 510 cbTopologyExists.addActionListener(new ActionListener() 511 { 512 @Override 513 public void actionPerformed(ActionEvent ev) 514 { 515 if (cbTopologyExists.isSelected()) 516 { 517 rbReplicated.setSelected(true); 518 } 519 } 520 }); 521 } 522 523 /** Enables/disables the fields. */ 524 private void checkEnablingState() 525 { 526 boolean enableFields = rbReplicated.isSelected() && 527 cbTopologyExists.isSelected(); 528 529 for (JTextComponent tf : hmFields.values()) 530 { 531 tf.setEnabled(enableFields); 532 } 533 534 for (JLabel l : hmLabels.values()) 535 { 536 l.setEnabled(enableFields); 537 } 538 539 cbTopologyExists.setEnabled(rbReplicated.isSelected()); 540 getLabel(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected()); 541 getField(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected()); 542 cbSecureReplication.setEnabled(rbReplicated.isSelected()); 543 } 544 545 /** 546 * Returns the label associated with the given field name. 547 * @param fieldName the field name for which we want to retrieve the JLabel. 548 * @return the label associated with the given field name. 549 */ 550 private JLabel getLabel(FieldName fieldName) 551 { 552 return hmLabels.get(fieldName); 553 } 554 555 /** 556 * Returns the JTextComponent associated with the given field name. 557 * @param fieldName the field name for which we want to retrieve the 558 * JTextComponent. 559 * @return the JTextComponent associated with the given field name. 560 */ 561 private JTextComponent getField(FieldName fieldName) 562 { 563 return hmFields.get(fieldName); 564 } 565}