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