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 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2015 ForgeRock AS. 016 */ 017package org.opends.server.config; 018 019import static org.opends.messages.ConfigMessages.*; 020 021import java.util.Iterator; 022import java.util.LinkedHashSet; 023import java.util.List; 024 025import javax.management.AttributeList; 026import javax.management.MBeanAttributeInfo; 027import javax.management.MBeanParameterInfo; 028 029import org.forgerock.i18n.LocalizableMessage; 030import org.forgerock.opendj.ldap.ByteString; 031import org.forgerock.opendj.ldap.schema.Syntax; 032import org.opends.server.types.Attribute; 033 034/** 035 * This class defines a configuration attribute, which can hold zero or more 036 * values associated with a configurable property within the Directory Server. 037 * Subclasses should define and enforce actual data types. 038 */ 039@org.opends.server.types.PublicAPI( 040 stability=org.opends.server.types.StabilityLevel.VOLATILE, 041 mayInstantiate=true, 042 mayExtend=true, 043 mayInvoke=true) 044public abstract class ConfigAttribute 045{ 046 /** 047 * Indicates whether this configuration attribute has pending changes that 048 * will be applied after appropriate administrative action has been performed. 049 */ 050 private boolean hasPendingValues; 051 052 /** Indicates whether this configuration attribute may have multiple values. */ 053 private boolean isMultiValued; 054 055 /** Indicates whether this configuration attribute is required to have a value. */ 056 private boolean isRequired; 057 058 /** 059 * Indicates whether changes to this attribute require administrative action 060 * before they will take effect. 061 */ 062 private boolean requiresAdminAction; 063 064 /** 065 * The value or set of values that are currently in effect for this 066 * configuration attribute. 067 */ 068 private LinkedHashSet<ByteString> activeValues; 069 070 /** 071 * The value or set of values that will be in effect once the appropriate 072 * administrative action has been taken. 073 */ 074 private LinkedHashSet<ByteString> pendingValues; 075 076 /** The description for this configuration attribute. */ 077 private LocalizableMessage description; 078 079 /** The name for this configuration attribute. */ 080 private String name; 081 082 083 084 /** 085 * Creates a new configuration attribute stub with the provided information 086 * but no values. The values will be set using the 087 * <CODE>setInitialValue</CODE> method. 088 * 089 * @param name The name for this configuration attribute. 090 * @param description The description for this configuration 091 * attribute. 092 * @param isRequired Indicates whether this configuration attribute 093 * is required to have at least one value. 094 * @param isMultiValued Indicates whether this configuration attribute 095 * may have multiple values. 096 * @param requiresAdminAction Indicates whether changes to this 097 * configuration attribute require administrative 098 * action before they will take effect. 099 */ 100 protected ConfigAttribute(String name, LocalizableMessage description, 101 boolean isRequired, boolean isMultiValued, 102 boolean requiresAdminAction) 103 { 104 this.name = name; 105 this.description = description; 106 this.isRequired = isRequired; 107 this.isMultiValued = isMultiValued; 108 this.requiresAdminAction = requiresAdminAction; 109 110 hasPendingValues = false; 111 activeValues = new LinkedHashSet<>(); 112 pendingValues = activeValues; 113 } 114 115 116 117 /** 118 * Creates a new configuration attribute with the provided information. 119 * 120 * @param name The name for this configuration attribute. 121 * @param description The description for this configuration 122 * attribute. 123 * @param isRequired Indicates whether this configuration attribute 124 * is required to have at least one value. 125 * @param isMultiValued Indicates whether this configuration attribute 126 * may have multiple values. 127 * @param requiresAdminAction Indicates whether changes to this 128 * configuration attribute require administrative 129 * action before they will take effect. 130 * @param activeValues The set of values for this attribute that are 131 * currently active. 132 */ 133 protected ConfigAttribute(String name, LocalizableMessage description, 134 boolean isRequired, boolean isMultiValued, 135 boolean requiresAdminAction, 136 LinkedHashSet<ByteString> activeValues) 137 { 138 this.name = name; 139 this.description = description; 140 this.isRequired = isRequired; 141 this.isMultiValued = isMultiValued; 142 this.requiresAdminAction = requiresAdminAction; 143 this.hasPendingValues = false; 144 145 this.activeValues = notNull(activeValues); 146 this.pendingValues = this.activeValues; 147 } 148 149 150 151 /** 152 * Creates a new configuration attribute with the provided information. 153 * 154 * @param name The name for this configuration attribute. 155 * @param description The description for this configuration 156 * attribute. 157 * @param isRequired Indicates whether this configuration attribute 158 * is required to have at least one value. 159 * @param isMultiValued Indicates whether this configuration attribute 160 * may have multiple values. 161 * @param requiresAdminAction Indicates whether changes to this 162 * configuration attribute require administrative 163 * action before they will take effect. 164 * @param activeValues The set of values for this attribute that are 165 * currently active. 166 * @param hasPendingValues Indicates whether this attribute has any 167 * pending values that will take effect after 168 * appropriate administrative action. 169 * @param pendingValues The set of values for this attribute that will 170 * be in effect after the appropriate 171 * administrative action is taken. This may be 172 * <CODE>null</CODE> if changes will take effect 173 * immediately. 174 */ 175 protected ConfigAttribute(String name, LocalizableMessage description, 176 boolean isRequired, boolean isMultiValued, 177 boolean requiresAdminAction, 178 LinkedHashSet<ByteString> activeValues, 179 boolean hasPendingValues, 180 LinkedHashSet<ByteString> pendingValues) 181 { 182 this.name = name; 183 this.description = description; 184 this.isRequired = isRequired; 185 this.isMultiValued = isMultiValued; 186 this.requiresAdminAction = requiresAdminAction; 187 this.hasPendingValues = hasPendingValues; 188 189 this.activeValues = notNull(activeValues); 190 191 if (!hasPendingValues) 192 { 193 this.pendingValues = this.activeValues; 194 } 195 else 196 { 197 this.pendingValues = notNull(pendingValues); 198 } 199 } 200 201 202 203 /** 204 * Retrieves the name for this configuration attribute. 205 * 206 * @return The name for this configuration attribute. 207 */ 208 public String getName() 209 { 210 return name; 211 } 212 213 214 215 /** 216 * Retrieves the description for this configuration attribute. 217 * 218 * @return The description for this configuration attribute, or 219 * <CODE>null</CODE> if there is no description. 220 */ 221 public LocalizableMessage getDescription() 222 { 223 return description; 224 } 225 226 227 228 /** 229 * Retrieves the name of the data type for this configuration attribute. This 230 * is for informational purposes (e.g., inclusion in method signatures and 231 * other kinds of descriptions) and does not necessarily need to map to an 232 * actual Java type. 233 * 234 * @return The name of the data type for this configuration attribute. 235 */ 236 public abstract String getDataType(); 237 238 239 240 /** 241 * Retrieves the attribute syntax for this configuration attribute. 242 * 243 * @return The attribute syntax for this configuration attribute. 244 */ 245 public abstract Syntax getSyntax(); 246 247 248 249 /** 250 * Indicates whether this configuration attribute is required to have at least 251 * one value. 252 * 253 * @return <CODE>true</CODE> if this configuration attribute is required to 254 * have at least one value, or <CODE>false</CODE> if not. 255 */ 256 public boolean isRequired() 257 { 258 return isRequired; 259 } 260 261 262 263 /** 264 * Indicates whether this configuration attribute may have multiple values. 265 * 266 * @return <CODE>true</CODE> if this configuration attribute may have 267 * multiple values, or <CODE>false</CODE> if not. 268 */ 269 public boolean isMultiValued() 270 { 271 return isMultiValued; 272 } 273 274 275 276 /** 277 * Indicates whether changes to this configuration attribute require 278 * administrative action before they will take effect. 279 * 280 * @return <CODE>true</CODE> if changes to this configuration attribute 281 * require administrative action before they will take effect, or 282 * <CODE>false</CODE> if changes will take effect immediately. 283 */ 284 public boolean requiresAdminAction() 285 { 286 return requiresAdminAction; 287 } 288 289 290 291 /** 292 * Retrieves the set of active values for this configuration attribute. This 293 * must not be modified by the caller. 294 * 295 * @return The set of active values for this configuration attribute. 296 */ 297 public LinkedHashSet<ByteString> getActiveValues() 298 { 299 return activeValues; 300 } 301 302 303 304 /** 305 * Indicates whether this attribute has been altered and that there are a set 306 * of pending values that will take effect after appropriate administrative 307 * action. 308 * 309 * @return <CODE>true</CODE> if this attribute has pending values, or 310 * <CODE>false</CODE> if not. 311 */ 312 public boolean hasPendingValues() 313 { 314 return hasPendingValues; 315 } 316 317 318 319 /** 320 * Retrieves the set of values that this configuration attribute will have on 321 * restart or after any necessary administrative action is performed. For 322 * attributes whose changes take effect immediately, this will always be the 323 * same as the set of active values. This must not be modified by the caller. 324 * 325 * @return The set of values that this configuration attribute will have 326 * after any appropriate administrative action is taken. 327 */ 328 public LinkedHashSet<ByteString> getPendingValues() 329 { 330 if (requiresAdminAction) 331 { 332 return pendingValues; 333 } 334 return activeValues; 335 } 336 337 338 339 /** 340 * Indicates whether the provided value is acceptable for use in this 341 * attribute. If it is not acceptable, then the reason should be written into 342 * the provided buffer. 343 * 344 * @param value The value for which to make the determination. 345 * @param rejectReason A buffer into which a human-readable reason for the 346 * reject may be written. 347 * 348 * @return <CODE>true</CODE> if the provided value is acceptable for use in 349 * this attribute, or <CODE>false</CODE> if not. 350 */ 351 public abstract boolean valueIsAcceptable(ByteString value, 352 StringBuilder rejectReason); 353 354 355 356 /** 357 * Specifies the set of values for this configuration attribute. Each value 358 * will be validated using the <CODE>valueIsAcceptable</CODE> method, and 359 * only a single value will be allowed unless <CODE>isMultiValued</CODE> 360 * returns <CODE>true</CODE>. If the set of values is acceptable, then it 361 * will be set either as the active set of values if changes are to take 362 * effect immediately, or if not then it will be applied to the set of 363 * pending values. 364 * 365 * @param values The set of values to apply to this attribute. 366 * 367 * @throws ConfigException If the provided set of values is not acceptable 368 * for some reason. 369 */ 370 protected void setValues(LinkedHashSet<ByteString> values) 371 throws ConfigException 372 { 373 // If no values are provided, then check to see if this is a required 374 // attribute. If it is, then reject the change. 375 if (values == null || values.isEmpty()) 376 { 377 if (isRequired) 378 { 379 throw new ConfigException(ERR_CONFIG_ATTR_IS_REQUIRED.get(name)); 380 } 381 382 if (requiresAdminAction) 383 { 384 pendingValues = notNull(values); 385 hasPendingValues = true; 386 } 387 else 388 { 389 activeValues = notNull(values); 390 391 pendingValues = activeValues; 392 hasPendingValues = false; 393 } 394 395 return; 396 } 397 398 399 // We know that we have at least one value, so get it and see if it is OK. 400 Iterator<ByteString> iterator = values.iterator(); 401 ByteString value = iterator.next(); 402 StringBuilder rejectReason = new StringBuilder(); 403 404 if (! valueIsAcceptable(value, rejectReason)) 405 { 406 throw new ConfigException(ERR_CONFIG_ATTR_REJECTED_VALUE.get( 407 value, name, rejectReason)); 408 } 409 410 411 // If this is not a multivalued attribute but there were more values 412 // provided, then reject it. 413 if (! isMultiValued && iterator.hasNext()) 414 { 415 LocalizableMessage message = ERR_CONFIG_ATTR_SET_VALUES_IS_SINGLE_VALUED.get(name); 416 throw new ConfigException(message); 417 } 418 419 420 // Iterate through the remaining values to see if they are acceptable. 421 while (iterator.hasNext()) 422 { 423 value = iterator.next(); 424 if (! valueIsAcceptable(value, rejectReason)) 425 { 426 throw new ConfigException(ERR_CONFIG_ATTR_REJECTED_VALUE.get( 427 value, name, rejectReason)); 428 } 429 } 430 431 432 // If we've gotten here, then everything is OK. Make this the new active or 433 // pending value set depending on the configuration. 434 if (requiresAdminAction) 435 { 436 pendingValues = values; 437 hasPendingValues = true; 438 } 439 else 440 { 441 activeValues = values; 442 pendingValues = activeValues; 443 hasPendingValues = false; 444 445 } 446 } 447 448 private LinkedHashSet<ByteString> notNull(LinkedHashSet<ByteString> values) 449 { 450 return values != null ? values : new LinkedHashSet<ByteString>(); 451 } 452 453 /** 454 * Specifies the set of active values for this configuration attribute. No 455 * validation will be performed, and no checks will be made to determine if 456 * administrative action is required. 457 * 458 * @param values The set of active values for this configuration attribute. 459 */ 460 protected void setActiveValues(LinkedHashSet<ByteString> values) 461 { 462 activeValues = values; 463 } 464 465 466 467 /** 468 * Specifies the set of pending values for this configuration attribute. No 469 * validation will be performed, and no checks will be made to determine if 470 * administrative action is required. 471 * 472 * @param values The set of pending values for this configuration attribute. 473 */ 474 protected void setPendingValues(LinkedHashSet<ByteString> values) 475 { 476 pendingValues = values; 477 hasPendingValues = true; 478 } 479 480 481 482 /** 483 * Attempts to add the provided set of values to this configuration attribute. 484 * All of the appropriate validity checks will be performed, and the changes 485 * will be applied to either the active or pending values, depending on the 486 * configuration of this attribute. 487 * 488 * @param values The set of values to add to this configuration attribute. 489 * 490 * @throws ConfigException If a problem occurs while attempting to add the 491 * provided set of values to this configuration 492 * attribute. 493 */ 494 protected void addValues(List<ByteString> values) throws ConfigException 495 { 496 // If there are no values provided, then do nothing. 497 if (values == null) 498 { 499 return; 500 } 501 502 int numValues = values.size(); 503 if (numValues == 0) 504 { 505 return; 506 } 507 508 509 // Make sure that the value limit will not be exceeded for a single-valued 510 // attribute. 511 if (!isMultiValued) 512 { 513 if (numValues > 1 514 || (hasPendingValues && !pendingValues.isEmpty()) 515 || (!hasPendingValues && !activeValues.isEmpty())) 516 { 517 throw new ConfigException(ERR_CONFIG_ATTR_ADD_VALUES_IS_SINGLE_VALUED.get(name)); 518 } 519 } 520 521 522 // Create a temporary set of values that we will use for this change. It 523 // may not actually be applied if an error occurs for some reason. 524 final LinkedHashSet<ByteString> vals = getValues(); 525 LinkedHashSet<ByteString> tempValues = new LinkedHashSet<>(vals.size() + numValues); 526 527 // Iterate through all of the provided values. Make sure that each is 528 // acceptable for use and that it is not already contained in the value set. 529 StringBuilder rejectReason = new StringBuilder(); 530 for (ByteString value : values) 531 { 532 if (tempValues.contains(value)) 533 { 534 throw new ConfigException(ERR_CONFIG_ATTR_ADD_VALUES_ALREADY_EXISTS.get( 535 name, value)); 536 } 537 538 if (! valueIsAcceptable(value, rejectReason)) 539 { 540 throw new ConfigException(ERR_CONFIG_ATTR_REJECTED_VALUE.get( 541 value, name, rejectReason)); 542 } 543 } 544 545 546 // If we have gotten here, then everything is OK, so go ahead and assign 547 // the temporary value set to either the active or pending lists. 548 if (requiresAdminAction) 549 { 550 pendingValues = tempValues; 551 hasPendingValues = true; 552 } 553 else 554 { 555 activeValues = tempValues; 556 pendingValues = tempValues; 557 hasPendingValues = false; 558 } 559 } 560 561 private LinkedHashSet<ByteString> getValues() 562 { 563 return requiresAdminAction && hasPendingValues 564 ? pendingValues 565 : activeValues; 566 } 567 568 /** 569 * Attempts to remove the set of values from this configuration attribute. 570 * 571 * @param values The set of values to remove from this configuration 572 * attribute. 573 * 574 * @throws ConfigException If any of the provided values are not in the 575 * value set, or if this is a required attribute and 576 * the resulting value list would be empty. 577 */ 578 protected void removeValues(List<ByteString> values) throws ConfigException 579 { 580 // Create a temporary set of values that we will use for this change. It 581 // may not actually be applied if an error occurs for some reason. 582 LinkedHashSet<ByteString> tempValues = new LinkedHashSet<>(getValues()); 583 584 // Iterate through all the provided values and make sure that they are 585 // contained in the list. If not, then throw an exception. If so, then 586 // remove it. 587 for (ByteString value : values) 588 { 589 if (! tempValues.remove(value)) 590 { 591 throw new ConfigException(ERR_CONFIG_ATTR_NO_SUCH_VALUE.get(name, value)); 592 } 593 } 594 595 596 // If this is a required attribute, then make sure that it will have at 597 // least one value. 598 if (isRequired && tempValues.isEmpty()) 599 { 600 LocalizableMessage message = ERR_CONFIG_ATTR_IS_REQUIRED.get(name); 601 throw new ConfigException(message); 602 } 603 604 605 // If we have gotten here, then everything is OK, so go ahead and assign 606 // the temporary value set to either the active or pending lists. 607 if (requiresAdminAction) 608 { 609 pendingValues = tempValues; 610 hasPendingValues = true; 611 } 612 else 613 { 614 activeValues = tempValues; 615 pendingValues = tempValues; 616 hasPendingValues = false; 617 } 618 } 619 620 621 622 /** 623 * Removes all values from this configuration attribute. 624 * 625 * @throws ConfigException If this is a required attribute that must have at 626 * least one value. 627 */ 628 protected void removeAllValues() 629 throws ConfigException 630 { 631 if (isRequired) 632 { 633 LocalizableMessage message = ERR_CONFIG_ATTR_IS_REQUIRED.get(name); 634 throw new ConfigException(message); 635 } 636 637 638 if (requiresAdminAction) 639 { 640 if (pendingValues == null) 641 { 642 pendingValues = new LinkedHashSet<>(); 643 } 644 else 645 { 646 pendingValues.clear(); 647 } 648 649 hasPendingValues = true; 650 } 651 else 652 { 653 activeValues.clear(); 654 pendingValues = activeValues; 655 hasPendingValues = false; 656 } 657 } 658 659 660 661 /** 662 * Assigns the initial values to this configuration attribute. This will wipe 663 * out any previous active or pending values that may have been assigned, and 664 * it will not perform any validation on those values. This method must only 665 * be used to set the initial values for this attribute from the configuration 666 * repository and must not be called any other time. 667 * 668 * @param values The initial set of values to assign to this configuration 669 * attribute. 670 */ 671 public void setInitialValues(LinkedHashSet<ByteString> values) 672 { 673 if (values == null) 674 { 675 values = new LinkedHashSet<>(); 676 } 677 678 activeValues = values; 679 pendingValues = values; 680 hasPendingValues = false; 681 } 682 683 684 685 /** 686 * Applies the set of pending values, making them the active values for this 687 * configuration attribute. This will not take any action if there are no 688 * pending values. 689 */ 690 public void applyPendingValues() 691 { 692 if (hasPendingValues) 693 { 694 activeValues = pendingValues; 695 hasPendingValues = false; 696 } 697 } 698 699 700 701 /** 702 * Converts the provided set of strings to a corresponding set of attribute 703 * values. 704 * 705 * @param valueStrings The set of strings to be converted into attribute 706 * values. 707 * @param allowFailures Indicates whether the decoding process should allow 708 * any failures in which one or more values could be 709 * decoded but at least one could not. If this is 710 * <CODE>true</CODE> and such a condition is acceptable 711 * for the underlying attribute type, then the returned 712 * set of values should simply not include those 713 * undecodable values. 714 * 715 * @return The set of attribute values converted from the provided strings. 716 * 717 * @throws ConfigException If an unrecoverable problem occurs while 718 * performing the conversion. 719 */ 720 public abstract LinkedHashSet<ByteString> stringsToValues( 721 List<String> valueStrings, boolean allowFailures) throws ConfigException; 722 723 724 725 /** 726 * Converts the set of active values for this configuration attribute into a 727 * set of strings that may be stored in the configuration or represented over 728 * protocol. The string representation used by this method should be 729 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 730 * method. 731 * 732 * @return The string representations of the set of active values for this 733 * configuration attribute. 734 */ 735 public abstract List<String> activeValuesToStrings(); 736 737 738 739 /** 740 * Converts the set of pending values for this configuration attribute into a 741 * set of strings that may be stored in the configuration or represented over 742 * protocol. The string representation used by this method should be 743 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 744 * method. 745 * 746 * @return The string representations of the set of pending values for this 747 * configuration attribute, or <CODE>null</CODE> if there are no 748 * pending values. 749 */ 750 public abstract List<String> pendingValuesToStrings(); 751 752 753 754 /** 755 * Retrieves a new configuration attribute of this type that will contain the 756 * values from the provided attribute. 757 * 758 * @param attributeList The list of attributes to use to create the config 759 * attribute. The list must contain either one or two 760 * elements, with both attributes having the same base 761 * name and the only option allowed is ";pending" and 762 * only if this attribute is one that requires admin 763 * action before a change may take effect. 764 * 765 * @return The generated configuration attribute. 766 * 767 * @throws ConfigException If the provided attribute cannot be treated as a 768 * configuration attribute of this type (e.g., if 769 * one or more of the values of the provided 770 * attribute are not suitable for an attribute of 771 * this type, or if this configuration attribute is 772 * single-valued and the provided attribute has 773 * multiple values). 774 */ 775 public abstract ConfigAttribute getConfigAttribute(List<Attribute> 776 attributeList) 777 throws ConfigException; 778 779 780 781 /** 782 * Retrieves a JMX attribute containing the active value set for this 783 * configuration attribute. 784 * 785 * @return A JMX attribute containing the active value set for this 786 * configuration attribute. 787 */ 788 public abstract javax.management.Attribute toJMXAttribute(); 789 790 /** 791 * Retrieves a JMX attribute containing the pending value set for this 792 * configuration attribute. 793 * 794 * @return A JMX attribute containing the pending value set for this 795 * configuration attribute. 796 */ 797 public abstract javax.management.Attribute toJMXAttributePending(); 798 799 800 801 /** 802 * Adds information about this configuration attribute to the provided JMX 803 * attribute list. If this configuration attribute requires administrative 804 * action before changes take effect and it has a set of pending values, then 805 * two attributes should be added to the list -- one for the active value 806 * and one for the pending value. The pending value should be named with 807 * the pending option. 808 * 809 * @param attributeList The attribute list to which the JMX attribute(s) 810 * should be added. 811 */ 812 public abstract void toJMXAttribute(AttributeList attributeList); 813 814 815 816 /** 817 * Adds information about this configuration attribute to the provided list in 818 * the form of a JMX <CODE>MBeanAttributeInfo</CODE> object. If this 819 * configuration attribute requires administrative action before changes take 820 * effect and it has a set of pending values, then two attribute info objects 821 * should be added to the list -- one for the active value (which should be 822 * read-write) and one for the pending value (which should be read-only). The 823 * pending value should be named with the pending option. 824 * 825 * @param attributeInfoList The list to which the attribute information 826 * should be added. 827 */ 828 public abstract void toJMXAttributeInfo(List<MBeanAttributeInfo> 829 attributeInfoList); 830 831 832 833 /** 834 * Retrieves a JMX <CODE>MBeanParameterInfo</CODE> object that describes this 835 * configuration attribute. 836 * 837 * @return A JMX <CODE>MBeanParameterInfo</CODE> object that describes this 838 * configuration attribute. 839 */ 840 public abstract MBeanParameterInfo toJMXParameterInfo(); 841 842 843 844 /** 845 * Attempts to set the value of this configuration attribute based on the 846 * information in the provided JMX attribute. 847 * 848 * @param jmxAttribute The JMX attribute to use to attempt to set the value 849 * of this configuration attribute. 850 * 851 * @throws ConfigException If the provided JMX attribute does not have an 852 * acceptable value for this configuration 853 * attribute. 854 */ 855 public abstract void setValue(javax.management.Attribute jmxAttribute) 856 throws ConfigException; 857 858 859 860 /** 861 * Creates a duplicate of this configuration attribute. 862 * 863 * @return A duplicate of this configuration attribute. 864 */ 865 public abstract ConfigAttribute duplicate(); 866 867 /** 868 * Creates the appropriate value set with the provided value. 869 * 870 * @param value 871 * The value to use to create the value set. 872 * @return The value set constructed from the provided value. 873 */ 874 static LinkedHashSet<ByteString> getValueSet(String value) 875 { 876 LinkedHashSet<ByteString> valueSet = new LinkedHashSet<>(1); 877 valueSet.add(ByteString.valueOfUtf8(value)); 878 return valueSet; 879 } 880 881 /** 882 * Creates the appropriate value set with the provided values. 883 * 884 * @param values 885 * The values to use to create the value set. 886 * @return The constructed value set. 887 */ 888 static LinkedHashSet<ByteString> getValueSet(List<String> values) 889 { 890 if (values == null) 891 { 892 return null; 893 } 894 895 LinkedHashSet<ByteString> valueSet = new LinkedHashSet<>(values.size()); 896 for (String value : values) 897 { 898 valueSet.add(ByteString.valueOfUtf8(value)); 899 } 900 return valueSet; 901 } 902}