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-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.ui; 028 029import static org.opends.messages.AdminToolMessages.*; 030import static com.forgerock.opendj.cli.Utils.isDN; 031 032import java.awt.Component; 033import java.awt.GridBagConstraints; 034import java.awt.GridBagLayout; 035import java.util.ArrayList; 036import java.util.Collection; 037 038import javax.swing.JLabel; 039import javax.swing.JPanel; 040import javax.swing.JScrollPane; 041import javax.swing.JTextArea; 042import javax.swing.JTextField; 043import javax.swing.event.ChangeEvent; 044import javax.swing.event.ChangeListener; 045import javax.swing.text.JTextComponent; 046 047import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 048import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; 049import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 050import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 051import org.opends.guitools.controlpanel.task.Task; 052import org.opends.guitools.controlpanel.ui.components.BasicExpander; 053import org.opends.guitools.controlpanel.util.Utilities; 054import org.forgerock.i18n.LocalizableMessage; 055import org.opends.server.protocols.ldap.LDAPFilter; 056import org.opends.server.types.DN; 057import org.opends.server.types.LDAPException; 058 059/** 060 * Abstract class used to refactor some code used by the import LDIF and export 061 * LDIF panels. 062 * 063 */ 064public abstract class InclusionExclusionPanel extends StatusGenericPanel 065{ 066 private static final long serialVersionUID = -3826176895778069011L; 067 /** 068 * The DNs to exclude. 069 */ 070 protected JTextArea dnsToExclude; 071 /** 072 * The attributes to exclude. 073 */ 074 protected JTextField attributesToExclude; 075 /** 076 * The exclusion filter. 077 */ 078 protected JTextField exclusionFilter; 079 /** 080 * The DNs to include. 081 */ 082 protected JTextArea dnsToInclude; 083 /** 084 * The attributes to include. 085 */ 086 protected JTextField attributesToInclude; 087 /** 088 * The inclusion filter. 089 */ 090 protected JTextField inclusionFilter; 091 092 /** 093 * The DNs to include. 094 */ 095 protected JLabel lDnsToInclude; 096 /** 097 * The attributes to include. 098 */ 099 protected JLabel lAttributesToInclude; 100 /** 101 * The inclusion filter label. 102 */ 103 protected JLabel lInclusionFilter; 104 /** 105 * The DNs to exclude label. 106 */ 107 protected JLabel lDnsToExclude; 108 /** 109 * The attributes to exclude label. 110 */ 111 protected JLabel lAttributesToExclude; 112 /** 113 * The exclusion filter label. 114 */ 115 protected JLabel lExclusionFilter; 116 117 /** {@inheritDoc} */ 118 public void cancelClicked() 119 { 120 setPrimaryValid(lDnsToInclude); 121 setPrimaryValid(lAttributesToInclude); 122 setPrimaryValid(lInclusionFilter); 123 setPrimaryValid(lDnsToExclude); 124 setPrimaryValid(lAttributesToExclude); 125 setPrimaryValid(lExclusionFilter); 126 super.cancelClicked(); 127 } 128 129 /** 130 * A commodity method that layouts a set of components. 131 * @param extraComponentLabels the labels. 132 * @param extraComponents the components. 133 * @return the panel containing the labels and the components. 134 */ 135 protected Component createDataInclusionOptions( 136 final JLabel[] extraComponentLabels, 137 final Component[] extraComponents) 138 { 139 JPanel panel = new JPanel(new GridBagLayout()); 140 panel.setOpaque(false); 141 GridBagConstraints gbc = new GridBagConstraints(); 142 gbc.weightx = 1.0; 143 gbc.gridwidth = 2; 144 gbc.gridx = 0; 145 gbc.gridy = 0; 146 gbc.anchor = GridBagConstraints.NORTHWEST; 147 gbc.fill = GridBagConstraints.HORIZONTAL; 148 int labelInsetLeft = 15; 149 final BasicExpander expander = 150 new BasicExpander(INFO_CTRL_PANEL_DATA_INCLUSION_OPTIONS.get()); 151 panel.add(expander, gbc); 152 153 gbc.gridy ++; 154 lDnsToInclude = 155 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DNS_TO_INCLUDE.get()); 156 gbc.insets.left = labelInsetLeft; 157 gbc.anchor = GridBagConstraints.NORTHWEST; 158 gbc.insets.top = 10; 159 gbc.gridwidth = 1; 160 gbc.weightx = 0.0; 161 panel.add(lDnsToInclude, gbc); 162 163 gbc.gridx = 1; 164 gbc.weightx = 1.0; 165 gbc.insets.left = 10; 166 dnsToInclude = Utilities.createTextArea(LocalizableMessage.EMPTY, 5, 25); 167 final JScrollPane scrollDns = Utilities.createScrollPane(dnsToInclude); 168 panel.add(scrollDns, gbc); 169 lDnsToInclude.setLabelFor(dnsToInclude); 170 171 gbc.insets.top = 2; 172 gbc.gridy ++; 173 final JLabel lDnsExplanation = Utilities.createInlineHelpLabel( 174 INFO_CTRL_PANEL_SEPARATE_DNS_LINE_BREAK.get()); 175 panel.add(lDnsExplanation, gbc); 176 177 gbc.gridy ++; 178 gbc.gridx = 0; 179 gbc.weightx = 0.0; 180 lAttributesToInclude = Utilities.createPrimaryLabel( 181 INFO_CTRL_PANEL_ATTRIBUTES_TO_INCLUDE.get()); 182 gbc.insets.left = labelInsetLeft; 183 gbc.anchor = GridBagConstraints.NORTHWEST; 184 gbc.insets.top = 10; 185 gbc.gridwidth = 1; 186 panel.add(lAttributesToInclude, gbc); 187 188 gbc.gridx = 1; 189 gbc.weightx = 1.0; 190 gbc.insets.left = 10; 191 gbc.weightx = 1.0; 192 attributesToInclude = Utilities.createMediumTextField(); 193 panel.add(attributesToInclude, gbc); 194 lAttributesToInclude.setLabelFor(attributesToInclude); 195 196 gbc.insets.top = 2; 197 gbc.gridy ++; 198 final JLabel lAttributesExplanation = Utilities.createInlineHelpLabel( 199 INFO_CTRL_PANEL_SEPARATE_ATTRIBUTES_COMMA.get()); 200 panel.add(lAttributesExplanation, gbc); 201 202 gbc.gridy ++; 203 gbc.gridx = 0; 204 lInclusionFilter = Utilities.createPrimaryLabel( 205 INFO_CTRL_PANEL_INCLUSION_FILTER.get()); 206 gbc.insets.left = labelInsetLeft; 207 gbc.anchor = GridBagConstraints.NORTHWEST; 208 gbc.insets.top = 10; 209 gbc.gridwidth = 1; 210 gbc.weightx = 0.0; 211 panel.add(lInclusionFilter, gbc); 212 213 gbc.gridx = 1; 214 gbc.weightx = 1.0; 215 gbc.insets.left = 10; 216 inclusionFilter = Utilities.createMediumTextField(); 217 panel.add(inclusionFilter, gbc); 218 lInclusionFilter.setLabelFor(inclusionFilter); 219 220 addExtraComponents(panel, extraComponentLabels, extraComponents, gbc, 221 labelInsetLeft); 222 223 ChangeListener changeListener = new ChangeListener() 224 { 225 /** {@inheritDoc} */ 226 public void stateChanged(ChangeEvent e) 227 { 228 lDnsToInclude.setVisible(expander.isSelected()); 229 scrollDns.setVisible(expander.isSelected()); 230 lDnsExplanation.setVisible(expander.isSelected()); 231 lAttributesToInclude.setVisible(expander.isSelected()); 232 attributesToInclude.setVisible(expander.isSelected()); 233 lAttributesExplanation.setVisible(expander.isSelected()); 234 lInclusionFilter.setVisible(expander.isSelected()); 235 inclusionFilter.setVisible(expander.isSelected()); 236 expanderStateChanged(expander, extraComponentLabels, extraComponents); 237 } 238 }; 239 expander.addChangeListener(changeListener); 240 expander.setSelected(false); 241 changeListener.stateChanged(null); 242 243 return panel; 244 } 245 246 /** 247 * A commodity method that layouts a set of components. 248 * @param extraComponentLabels the labels. 249 * @param extraComponents the components. 250 * @return the panel containing the labels and the components. 251 */ 252 protected Component createDataExclusionOptions( 253 final JLabel[] extraComponentLabels, 254 final Component[] extraComponents) 255 { 256 JPanel panel = new JPanel(new GridBagLayout()); 257 panel.setOpaque(false); 258 GridBagConstraints gbc = new GridBagConstraints(); 259 gbc.weightx = 1.0; 260 gbc.gridwidth = 2; 261 gbc.gridx = 0; 262 gbc.gridy = 0; 263 gbc.anchor = GridBagConstraints.NORTHWEST; 264 gbc.fill = GridBagConstraints.HORIZONTAL; 265 int labelInsetLeft = 15; 266 final BasicExpander expander = 267 new BasicExpander(INFO_CTRL_PANEL_DATA_EXCLUSION_OPTIONS.get()); 268 panel.add(expander, gbc); 269 270 gbc.gridy ++; 271 lDnsToExclude = 272 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DNS_TO_EXCLUDE.get()); 273 gbc.insets.left = labelInsetLeft; 274 gbc.anchor = GridBagConstraints.NORTHWEST; 275 gbc.insets.top = 10; 276 gbc.gridwidth = 1; 277 gbc.weightx = 0.0; 278 panel.add(lDnsToExclude, gbc); 279 280 gbc.gridx = 1; 281 gbc.weightx = 1.0; 282 gbc.insets.left = 10; 283 dnsToExclude = Utilities.createTextArea(LocalizableMessage.EMPTY, 5, 0); 284 final JScrollPane scrollDns = Utilities.createScrollPane(dnsToExclude); 285 lDnsToExclude.setLabelFor(dnsToExclude); 286 panel.add(scrollDns, gbc); 287 288 gbc.insets.top = 2; 289 gbc.gridy ++; 290 final JLabel lDnsExplanation = Utilities.createInlineHelpLabel( 291 INFO_CTRL_PANEL_SEPARATE_DNS_LINE_BREAK.get()); 292 panel.add(lDnsExplanation, gbc); 293 294 gbc.gridy ++; 295 gbc.gridx = 0; 296 gbc.weightx = 0.0; 297 lAttributesToExclude = Utilities.createPrimaryLabel( 298 INFO_CTRL_PANEL_ATTRIBUTES_TO_EXCLUDE.get()); 299 gbc.insets.left = labelInsetLeft; 300 gbc.anchor = GridBagConstraints.NORTHWEST; 301 gbc.insets.top = 10; 302 gbc.gridwidth = 1; 303 panel.add(lAttributesToExclude, gbc); 304 305 gbc.gridx = 1; 306 gbc.weightx = 1.0; 307 gbc.insets.left = 10; 308 gbc.weightx = 1.0; 309 attributesToExclude = Utilities.createTextField(); 310 panel.add(attributesToExclude, gbc); 311 lAttributesToExclude.setLabelFor(dnsToExclude); 312 313 gbc.insets.top = 2; 314 gbc.gridy ++; 315 final JLabel lAttributesExplanation = Utilities.createInlineHelpLabel( 316 INFO_CTRL_PANEL_SEPARATE_ATTRIBUTES_COMMA.get()); 317 panel.add(lAttributesExplanation, gbc); 318 lAttributesExplanation.setLabelFor(dnsToExclude); 319 320 gbc.gridy ++; 321 gbc.gridx = 0; 322 lExclusionFilter = Utilities.createPrimaryLabel( 323 INFO_CTRL_PANEL_EXCLUSION_FILTER.get()); 324 gbc.insets.left = labelInsetLeft; 325 gbc.anchor = GridBagConstraints.NORTHWEST; 326 gbc.insets.top = 10; 327 gbc.gridwidth = 1; 328 gbc.weightx = 0.0; 329 panel.add(lExclusionFilter, gbc); 330 331 gbc.gridx = 1; 332 gbc.weightx = 1.0; 333 gbc.insets.left = 10; 334 exclusionFilter = Utilities.createTextField(); 335 panel.add(exclusionFilter, gbc); 336 lExclusionFilter.setLabelFor(exclusionFilter); 337 338 addExtraComponents(panel, extraComponentLabels, extraComponents, gbc, 339 labelInsetLeft); 340 341 ChangeListener changeListener = new ChangeListener() 342 { 343 /** {@inheritDoc} */ 344 public void stateChanged(ChangeEvent e) 345 { 346 lDnsToExclude.setVisible(expander.isSelected()); 347 scrollDns.setVisible(expander.isSelected()); 348 lDnsExplanation.setVisible(expander.isSelected()); 349 lAttributesToExclude.setVisible(expander.isSelected()); 350 attributesToExclude.setVisible(expander.isSelected()); 351 lAttributesExplanation.setVisible(expander.isSelected()); 352 lExclusionFilter.setVisible(expander.isSelected()); 353 exclusionFilter.setVisible(expander.isSelected()); 354 expanderStateChanged(expander, extraComponentLabels, extraComponents); 355 } 356 }; 357 expander.addChangeListener(changeListener); 358 expander.setSelected(false); 359 changeListener.stateChanged(null); 360 361 return panel; 362 } 363 364 private void addExtraComponents(JPanel panel, JLabel[] extraComponentLabels, 365 Component[] extraComponents, GridBagConstraints gbc, int labelInsetLeft) 366 { 367 for (int i=0; i<extraComponentLabels.length; i++) 368 { 369 gbc.gridy ++; 370 gbc.gridx = 0; 371 gbc.insets.left = labelInsetLeft; 372 gbc.anchor = GridBagConstraints.NORTHWEST; 373 gbc.insets.top = 10; 374 375 if (extraComponentLabels[i] == null) 376 { 377 gbc.gridwidth = 2; 378 gbc.weightx = 1.0; 379 panel.add(extraComponents[i], gbc); 380 } 381 else 382 { 383 gbc.gridwidth = 1; 384 gbc.weightx = 0.0; 385 panel.add(extraComponentLabels[i], gbc); 386 387 gbc.gridx = 1; 388 gbc.weightx = 1.0; 389 gbc.insets.left = 10; 390 panel.add(extraComponents[i], gbc); 391 392 extraComponentLabels[i].setLabelFor(extraComponents[i]); 393 } 394 } 395 } 396 397 private void expanderStateChanged(BasicExpander expander, 398 JLabel[] extraComponentLabels, 399 Component[] extraComponents) 400 { 401 for (JLabel comp : extraComponentLabels) 402 { 403 if (comp != null) 404 { 405 comp.setVisible(expander.isSelected()); 406 } 407 } 408 for (Component comp : extraComponents) 409 { 410 comp.setVisible(expander.isSelected()); 411 } 412 } 413 414 415 /** 416 * Updates a list of errors in the include and exclude subpanels. 417 * @param errors the list of errors to be updated. 418 * @param backendName the name of the backend where the operation associated 419 * with the panel applies (used to generate the error messages). 420 */ 421 protected void updateIncludeExclude(Collection<LocalizableMessage> errors, 422 String backendName) 423 { 424 updateErrors(lDnsToInclude, dnsToInclude, lAttributesToInclude, 425 attributesToInclude, lInclusionFilter, inclusionFilter, errors, 426 backendName); 427 updateErrors(lDnsToExclude, dnsToExclude, lAttributesToExclude, 428 attributesToExclude, lExclusionFilter, exclusionFilter, errors, 429 backendName); 430 } 431 432 433 private void updateErrors(JLabel lDns, JTextComponent dns, JLabel lAttributes, 434 JTextComponent attributes, JLabel lFilter, JTextComponent filter, 435 Collection<LocalizableMessage> errors, String backendName) 436 { 437 setPrimaryValid(lDns); 438 setPrimaryValid(lAttributes); 439 setPrimaryValid(lFilter); 440 441 String s = dns.getText(); 442 443 boolean validDn = true; 444 445 if (s.trim().length() > 0) 446 { 447 String[] dnArray = s.split("\n"); 448 for (int i=0; i<dnArray.length; i++) 449 { 450 if (!isDN(dnArray[i])) 451 { 452 errors.add(ERR_CTRL_PANEL_DN_NOT_VALID_WITH_VALUE.get(dnArray[i])); 453 validDn = false; 454 } 455 else 456 { 457 BackendDescriptor backend = null; 458 459 if (backendName != null) 460 { 461 ServerDescriptor server = getInfo().getServerDescriptor(); 462 for (BackendDescriptor b : server.getBackends()) 463 { 464 if (b.getBackendID().equalsIgnoreCase(backendName)) 465 { 466 backend = b; 467 break; 468 } 469 } 470 } 471 472 if (backend != null) 473 { 474 boolean found = false; 475 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 476 { 477 try 478 { 479 DN dn = DN.valueOf(dnArray[i]); 480 if (dn.isDescendantOf(baseDN.getDn())) 481 { 482 found = true; 483 break; 484 } 485 } 486 catch (Throwable t) 487 { 488 // Bug 489 t.printStackTrace(); 490 } 491 } 492 if (!found) 493 { 494 errors.add(ERR_CTRL_PANEL_NOT_A_DESCENDANT_OF_BASE_DN.get( 495 dnArray[i], backendName)); 496 } 497 } 498 } 499 } 500 } 501 502 if (!validDn) 503 { 504 setPrimaryInvalid(lDns); 505 } 506 507 s = attributes.getText(); 508 509 boolean validAttributes = true; 510 511 if (s.trim().length() > 0) 512 { 513 String[] attributeArray = s.split(","); 514 for (int i=0; i<attributeArray.length; i++) 515 { 516 if (!Utilities.isValidAttributeName(attributeArray[i])) 517 { 518 errors.add(ERR_CTRL_PANEL_NOT_VALID_ATTRIBUTE_NAME.get( 519 attributeArray[i])); 520 validAttributes = false; 521 } 522 } 523 } 524 525 if (!validAttributes) 526 { 527 setPrimaryInvalid(lAttributes); 528 } 529 530 s = filter.getText(); 531 if (s != null && s.trim().length() > 0) 532 { 533 try 534 { 535 LDAPFilter.decode(s); 536 } 537 catch (LDAPException le) 538 { 539 errors.add(ERR_CTRL_PANEL_INVALID_FILTER_DETAILS_WITH_VALUE.get(s, le.getMessageObject())); 540 setPrimaryInvalid(lFilter); 541 } 542 } 543 } 544 545 /** 546 * Abstract class that provides some methods that can be used to generate the 547 * equivalent command-line arguments for some of the things that are contained 548 * in the inclusion/exclusion panels. 549 * 550 */ 551 protected abstract class InclusionExclusionTask extends Task 552 { 553 /** 554 * The constructor of the task. 555 * @param info the control panel info. 556 * @param dlg the progress dialog that shows the progress of the task. 557 */ 558 protected InclusionExclusionTask(ControlPanelInfo info, ProgressDialog dlg) 559 { 560 super(info, dlg); 561 } 562 563 /** 564 * Returns the command line arguments corresponding to the elements 565 * displayed in the inclusion/exclusion panels. 566 * @return the command line arguments corresponding to the elements 567 * displayed in the inclusion/exclusion panels. 568 */ 569 protected ArrayList<String> getCommandLineArguments() 570 { 571 ArrayList<String> args = new ArrayList<>(); 572 String s = dnsToInclude.getText(); 573 if (s.trim().length() > 0) 574 { 575 String[] dnArray = s.split("\n"); 576 for (int i=0; i<dnArray.length; i++) 577 { 578 args.add("--includeBranch"); 579 args.add(dnArray[i]); 580 } 581 } 582 s = attributesToInclude.getText(); 583 if (s.trim().length() > 0) 584 { 585 String[] attrArray = s.split(","); 586 for (int i=0; i<attrArray.length; i++) 587 { 588 args.add("--includeAttribute"); 589 args.add(attrArray[i]); 590 } 591 } 592 s = inclusionFilter.getText(); 593 if (s.trim().length() > 0) 594 { 595 args.add("--includeFilter"); 596 args.add(s); 597 } 598 599 s = dnsToExclude.getText(); 600 if (s.trim().length() > 0) 601 { 602 String[] dnArray = s.split("\n"); 603 for (int i=0; i<dnArray.length; i++) 604 { 605 args.add("--excludeBranch"); 606 args.add(dnArray[i]); 607 } 608 } 609 s = attributesToExclude.getText(); 610 if (s.trim().length() > 0) 611 { 612 String[] attrArray = s.split(","); 613 for (int i=0; i<attrArray.length; i++) 614 { 615 args.add("--excludeAttribute"); 616 args.add(attrArray[i]); 617 } 618 } 619 s = exclusionFilter.getText(); 620 if (s.trim().length() > 0) 621 { 622 args.add("--excludeFilter"); 623 args.add(s); 624 } 625 args.addAll(getConnectionCommandLineArguments()); 626 return args; 627 } 628 } 629}