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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.config; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 import java.util.LinkedHashSet; 034 import java.util.List; 035 import javax.management.AttributeList; 036 import javax.management.MBeanAttributeInfo; 037 import javax.management.MBeanParameterInfo; 038 039 import org.opends.server.api.AttributeSyntax; 040 import org.opends.server.core.DirectoryServer; 041 import org.opends.server.protocols.asn1.ASN1OctetString; 042 import org.opends.server.types.Attribute; 043 import org.opends.server.types.AttributeValue; 044 045 import static org.opends.server.config.ConfigConstants.*; 046 import static org.opends.messages.ConfigMessages.*; 047 /** 048 * This class defines a configuration attribute that is only intended for use 049 * in displaying information. It will not allow its value to be altered. 050 */ 051 @org.opends.server.types.PublicAPI( 052 stability=org.opends.server.types.StabilityLevel.VOLATILE, 053 mayInstantiate=true, 054 mayExtend=false, 055 mayInvoke=true) 056 public final class ReadOnlyConfigAttribute 057 extends ConfigAttribute 058 { 059 // The set of values for this attribute. 060 private List<String> values; 061 062 063 064 /** 065 * Creates a new read-only configuration attribute stub with the provided 066 * information but no values. The values will be set using the 067 * <CODE>setInitialValue</CODE> method. 068 * 069 * @param name The name for this configuration attribute. 070 * @param description The description for this configuration attribute. 071 * @param isMultiValued Indicates whether this configuration attribute may 072 * have multiple values. 073 */ 074 public ReadOnlyConfigAttribute(String name, Message description, 075 boolean isMultiValued) 076 { 077 super(name, description, false, isMultiValued, false); 078 079 080 values = new ArrayList<String>(); 081 } 082 083 084 085 /** 086 * Creates a new read-only configuration attribute with the provided 087 * information. 088 * 089 * @param name The name for this configuration attribute. 090 * @param description The description for this configuration attribute. 091 * @param value The value for this configuration attribute. 092 */ 093 public ReadOnlyConfigAttribute(String name, Message description, String value) 094 { 095 super(name, description, false, false, false, getValueSet(value)); 096 097 098 if (value == null) 099 { 100 values = new ArrayList<String>(0); 101 } 102 else 103 { 104 values = new ArrayList<String>(1); 105 values.add(value); 106 } 107 } 108 109 110 111 /** 112 * Creates a new read-only configuration attribute with the provided 113 * information. 114 * 115 * @param name The name for this configuration attribute. 116 * @param description The description for this configuration attribute. 117 * @param values The set of values for this configuration attribute. 118 */ 119 public ReadOnlyConfigAttribute(String name, Message description, 120 List<String> values) 121 { 122 super(name, description, false, true, false, getValueSet(values)); 123 124 125 if (values == null) 126 { 127 this.values = new ArrayList<String>(); 128 } 129 else 130 { 131 this.values = values; 132 } 133 } 134 135 136 137 /** 138 * Retrieves the name of the data type for this configuration attribute. This 139 * is for informational purposes (e.g., inclusion in method signatures and 140 * other kinds of descriptions) and does not necessarily need to map to an 141 * actual Java type. 142 * 143 * @return The name of the data type for this configuration attribute. 144 */ 145 public String getDataType() 146 { 147 return "ReadOnly"; 148 } 149 150 151 152 /** 153 * Retrieves the attribute syntax for this configuration attribute. 154 * 155 * @return The attribute syntax for this configuration attribute. 156 */ 157 public AttributeSyntax getSyntax() 158 { 159 return DirectoryServer.getDefaultStringSyntax(); 160 } 161 162 163 164 /** 165 * Retrieves the active value for this configuration attribute as a string. 166 * This is only valid for single-valued attributes that have a value. 167 * 168 * @return The active value for this configuration attribute as a string. 169 * 170 * @throws ConfigException If this attribute does not have exactly one 171 * active value. 172 */ 173 public String activeValue() 174 throws ConfigException 175 { 176 if ((values == null) || values.isEmpty()) 177 { 178 Message message = ERR_CONFIG_ATTR_NO_STRING_VALUE.get(getName()); 179 throw new ConfigException(message); 180 } 181 182 if (values.size() > 1) 183 { 184 Message message = ERR_CONFIG_ATTR_MULTIPLE_STRING_VALUES.get(getName()); 185 throw new ConfigException(message); 186 } 187 188 return values.get(0); 189 } 190 191 192 193 /** 194 * Retrieves the set of active values for this configuration attribute. 195 * 196 * @return The set of active values for this configuration attribute. 197 */ 198 public List<String> activeValues() 199 { 200 return values; 201 } 202 203 204 205 /** 206 * Retrieves the pending value for this configuration attribute as a string. 207 * This is only valid for single-valued attributes that have a value. If this 208 * attribute does not have any pending values, then the active value will be 209 * returned. 210 * 211 * @return The pending value for this configuration attribute as a string. 212 * 213 * @throws ConfigException If this attribute does not have exactly one 214 * pending value. 215 */ 216 public String pendingValue() 217 throws ConfigException 218 { 219 return activeValue(); 220 } 221 222 223 224 /** 225 * Retrieves the set of pending values for this configuration attribute. If 226 * there are no pending values, then the set of active values will be 227 * returned. 228 * 229 * @return The set of pending values for this configuration attribute. 230 */ 231 public List<String> pendingValues() 232 { 233 return activeValues(); 234 } 235 236 237 238 /** 239 * Sets the value for this string configuration attribute. 240 * 241 * @param value The value for this string configuration attribute. 242 * 243 * @throws ConfigException If the provided value is not acceptable. 244 */ 245 public void setValue(String value) 246 throws ConfigException 247 { 248 Message message = ERR_CONFIG_ATTR_READ_ONLY.get(getName()); 249 throw new ConfigException(message); 250 } 251 252 253 254 /** 255 * Sets the values for this string configuration attribute. 256 * 257 * @param values The set of values for this string configuration attribute. 258 * 259 * @throws ConfigException If the provided value set or any of the 260 * individual values are not acceptable. 261 */ 262 public void setValues(List<String> values) 263 throws ConfigException 264 { 265 Message message = ERR_CONFIG_ATTR_READ_ONLY.get(getName()); 266 throw new ConfigException(message); 267 } 268 269 270 271 /** 272 * Creates the appropriate value set with the provided value. 273 * 274 * @param value The value to use to create the value set. 275 * 276 * @return The constructed value set. 277 */ 278 private static LinkedHashSet<AttributeValue> getValueSet(String value) 279 { 280 LinkedHashSet<AttributeValue> valueSet = 281 new LinkedHashSet<AttributeValue>(1); 282 283 valueSet.add(new AttributeValue(new ASN1OctetString(value), 284 new ASN1OctetString(value))); 285 286 return valueSet; 287 } 288 289 290 291 /** 292 * Creates the appropriate value set with the provided values. 293 * 294 * @param values The values to use to create the value set. 295 * 296 * @return The constructed value set. 297 */ 298 private static LinkedHashSet<AttributeValue> getValueSet(List<String> values) 299 { 300 if (values == null) 301 { 302 return null; 303 } 304 305 LinkedHashSet<AttributeValue> valueSet = 306 new LinkedHashSet<AttributeValue>(values.size()); 307 308 for (String value : values) 309 { 310 valueSet.add(new AttributeValue(new ASN1OctetString(value), 311 new ASN1OctetString(value))); 312 } 313 314 return valueSet; 315 } 316 317 318 319 /** 320 * Applies the set of pending values, making them the active values for this 321 * configuration attribute. This will not take any action if there are no 322 * pending values. 323 */ 324 public void applyPendingValues() 325 { 326 } 327 328 329 330 /** 331 * Indicates whether the provided value is acceptable for use in this 332 * attribute. If it is not acceptable, then the reason should be written into 333 * the provided buffer. 334 * 335 * @param value The value for which to make the determination. 336 * @param rejectReason A buffer into which a human-readable reason for the 337 * reject may be written. 338 * 339 * @return <CODE>true</CODE> if the provided value is acceptable for use in 340 * this attribute, or <CODE>false</CODE> if not. 341 */ 342 public boolean valueIsAcceptable(AttributeValue value, 343 StringBuilder rejectReason) 344 { 345 rejectReason.append(ERR_CONFIG_ATTR_READ_ONLY.get(getName())); 346 return false; 347 } 348 349 350 351 /** 352 * Converts the provided set of strings to a corresponding set of attribute 353 * values. 354 * 355 * @param valueStrings The set of strings to be converted into attribute 356 * values. 357 * @param allowFailures Indicates whether the decoding process should allow 358 * any failures in which one or more values could be 359 * decoded but at least one could not. If this is 360 * <CODE>true</CODE> and such a condition is acceptable 361 * for the underlying attribute type, then the returned 362 * set of values should simply not include those 363 * undecodable values. 364 * 365 * @return The set of attribute values converted from the provided strings. 366 * 367 * @throws ConfigException If an unrecoverable problem occurs while 368 * performing the conversion. 369 */ 370 public LinkedHashSet<AttributeValue> 371 stringsToValues(List<String> valueStrings, 372 boolean allowFailures) 373 throws ConfigException 374 { 375 if ((valueStrings == null) || valueStrings.isEmpty()) 376 { 377 return new LinkedHashSet<AttributeValue>(); 378 } 379 380 381 int numValues = valueStrings.size(); 382 LinkedHashSet<AttributeValue> valueSet = 383 new LinkedHashSet<AttributeValue>(numValues); 384 for (String valueString : valueStrings) 385 { 386 valueSet.add(new AttributeValue(new ASN1OctetString(valueString), 387 new ASN1OctetString(valueString))); 388 } 389 390 391 return valueSet; 392 } 393 394 395 396 /** 397 * Converts the set of active values for this configuration attribute into a 398 * set of strings that may be stored in the configuration or represented over 399 * protocol. The string representation used by this method should be 400 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 401 * method. 402 * 403 * @return The string representations of the set of active values for this 404 * configuration attribute. 405 */ 406 public List<String> activeValuesToStrings() 407 { 408 return values; 409 } 410 411 412 413 /** 414 * Converts the set of pending values for this configuration attribute into a 415 * set of strings that may be stored in the configuration or represented over 416 * protocol. The string representation used by this method should be 417 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 418 * method. 419 * 420 * @return The string representations of the set of pending values for this 421 * configuration attribute, or <CODE>null</CODE> if there are no 422 * pending values. 423 */ 424 public List<String> pendingValuesToStrings() 425 { 426 return activeValuesToStrings(); 427 } 428 429 430 431 /** 432 * Retrieves a new configuration attribute of this type that will contain the 433 * values from the provided attribute. 434 * 435 * @param attributeList The list of attributes to use to create the config 436 * attribute. The list must contain either one or two 437 * elements, with both attributes having the same base 438 * name and the only option allowed is ";pending" and 439 * only if this attribute is one that requires admin 440 * action before a change may take effect. 441 * 442 * @return The generated configuration attribute. 443 * 444 * @throws ConfigException If the provided attribute cannot be treated as a 445 * configuration attribute of this type (e.g., if 446 * one or more of the values of the provided 447 * attribute are not suitable for an attribute of 448 * this type, or if this configuration attribute is 449 * single-valued and the provided attribute has 450 * multiple values). 451 */ 452 public ConfigAttribute getConfigAttribute(List<Attribute> attributeList) 453 throws ConfigException 454 { 455 // The attribute won't be present in the entry, so we'll just return a 456 // reference to this attribute. 457 return duplicate(); 458 } 459 460 461 462 /** 463 * Retrieves a JMX attribute containing the active value set for this 464 * configuration attribute. 465 * 466 * @return A JMX attribute containing the active value set for this 467 * configuration attribute, or <CODE>null</CODE> if it does not have 468 * any active values. 469 */ 470 public javax.management.Attribute toJMXAttribute() 471 { 472 if (isMultiValued()) 473 { 474 String[] valueArray = new String[values.size()]; 475 values.toArray(valueArray); 476 477 return new javax.management.Attribute(getName(), valueArray); 478 } 479 else 480 { 481 if (values.isEmpty()) 482 { 483 return null; 484 } 485 else 486 { 487 return new javax.management.Attribute(getName(), values.get(0)); 488 } 489 } 490 } 491 492 /** 493 * Retrieves a JMX attribute containing the pending value set for this 494 * configuration attribute. As this an read only attribute, this method 495 * should never be called 496 * 497 * @return A JMX attribute containing the pending value set for this 498 * configuration attribute, or <CODE>null</CODE> if it does 499 * not have any active values. 500 */ 501 public javax.management.Attribute toJMXAttributePending() 502 { 503 // Should never occurs !!! 504 return toJMXAttribute(); 505 } 506 507 508 509 /** 510 * Adds information about this configuration attribute to the provided JMX 511 * attribute list. If this configuration attribute requires administrative 512 * action before changes take effect and it has a set of pending values, then 513 * two attributes should be added to the list -- one for the active value 514 * and one for the pending value. The pending value should be named with 515 * the pending option. 516 * 517 * @param attributeList The attribute list to which the JMX attribute(s) 518 * should be added. 519 */ 520 public void toJMXAttribute(AttributeList attributeList) 521 { 522 javax.management.Attribute jmxAttr = toJMXAttribute(); 523 attributeList.add(jmxAttr); 524 } 525 526 527 528 /** 529 * Adds information about this configuration attribute to the provided list in 530 * the form of a JMX <CODE>MBeanAttributeInfo</CODE> object. If this 531 * configuration attribute requires administrative action before changes take 532 * effect and it has a set of pending values, then two attribute info objects 533 * should be added to the list -- one for the active value (which should be 534 * read-write) and one for the pending value (which should be read-only). The 535 * pending value should be named with the pending option. 536 * 537 * @param attributeInfoList The list to which the attribute information 538 * should be added. 539 */ 540 public void toJMXAttributeInfo(List<MBeanAttributeInfo> attributeInfoList) 541 { 542 if (isMultiValued()) 543 { 544 attributeInfoList.add(new MBeanAttributeInfo(getName(), 545 JMX_TYPE_STRING_ARRAY, 546 String.valueOf( 547 getDescription()), 548 true, false, false)); 549 } 550 else 551 { 552 attributeInfoList.add(new MBeanAttributeInfo(getName(), 553 String.class.getName(), 554 String.valueOf( 555 getDescription()), 556 true, false, false)); 557 } 558 } 559 560 561 562 /** 563 * Retrieves a JMX <CODE>MBeanParameterInfo</CODE> object that describes this 564 * configuration attribute. 565 * 566 * @return A JMX <CODE>MBeanParameterInfo</CODE> object that describes this 567 * configuration attribute. 568 */ 569 public MBeanParameterInfo toJMXParameterInfo() 570 { 571 if (isMultiValued()) 572 { 573 return new MBeanParameterInfo(getName(), JMX_TYPE_STRING_ARRAY, 574 String.valueOf(getDescription())); 575 } 576 else 577 { 578 return new MBeanParameterInfo(getName(), String.class.getName(), 579 String.valueOf(getDescription())); 580 } 581 } 582 583 584 585 /** 586 * Attempts to set the value of this configuration attribute based on the 587 * information in the provided JMX attribute. 588 * 589 * @param jmxAttribute The JMX attribute to use to attempt to set the value 590 * of this configuration attribute. 591 * 592 * @throws ConfigException If the provided JMX attribute does not have an 593 * acceptable value for this configuration 594 * attribute. 595 */ 596 public void setValue(javax.management.Attribute jmxAttribute) 597 throws ConfigException 598 { 599 Message message = ERR_CONFIG_ATTR_READ_ONLY.get(getName()); 600 throw new ConfigException(message); 601 } 602 603 604 605 /** 606 * Creates a duplicate of this configuration attribute. 607 * 608 * @return A duplicate of this configuration attribute. 609 */ 610 public ConfigAttribute duplicate() 611 { 612 return new ReadOnlyConfigAttribute(getName(), getDescription(), 613 activeValues()); 614 } 615 } 616