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 2006-2008 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.config; 028 029import java.util.ArrayList; 030import java.util.LinkedHashSet; 031import java.util.List; 032 033import javax.management.AttributeList; 034import javax.management.MBeanAttributeInfo; 035import javax.management.MBeanParameterInfo; 036 037import org.forgerock.i18n.LocalizableMessage; 038import org.forgerock.opendj.ldap.ByteString; 039import org.forgerock.opendj.ldap.schema.Syntax; 040import org.opends.server.core.DirectoryServer; 041import org.opends.server.types.Attribute; 042 043import static org.opends.messages.ConfigMessages.*; 044import static org.opends.server.config.ConfigConstants.*; 045import static org.opends.server.util.CollectionUtils.*; 046 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) 056public 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, LocalizableMessage description, 075 boolean isMultiValued) 076 { 077 super(name, description, false, isMultiValued, false); 078 079 080 values = new ArrayList<>(); 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, LocalizableMessage description, String value) 094 { 095 super(name, description, false, false, false, getValueSet(value)); 096 097 098 if (value == null) 099 { 100 values = new ArrayList<>(0); 101 } 102 else 103 { 104 values = newArrayList(value); 105 } 106 } 107 108 109 110 /** 111 * Creates a new read-only configuration attribute with the provided 112 * information. 113 * 114 * @param name The name for this configuration attribute. 115 * @param description The description for this configuration attribute. 116 * @param values The set of values for this configuration attribute. 117 */ 118 public ReadOnlyConfigAttribute(String name, LocalizableMessage description, 119 List<String> values) 120 { 121 super(name, description, false, true, false, getValueSet(values)); 122 123 124 if (values == null) 125 { 126 this.values = new ArrayList<>(); 127 } 128 else 129 { 130 this.values = values; 131 } 132 } 133 134 135 136 /** 137 * Retrieves the name of the data type for this configuration attribute. This 138 * is for informational purposes (e.g., inclusion in method signatures and 139 * other kinds of descriptions) and does not necessarily need to map to an 140 * actual Java type. 141 * 142 * @return The name of the data type for this configuration attribute. 143 */ 144 public String getDataType() 145 { 146 return "ReadOnly"; 147 } 148 149 150 151 /** 152 * Retrieves the attribute syntax for this configuration attribute. 153 * 154 * @return The attribute syntax for this configuration attribute. 155 */ 156 public Syntax getSyntax() 157 { 158 return DirectoryServer.getDefaultStringSyntax(); 159 } 160 161 162 163 /** 164 * Retrieves the active value for this configuration attribute as a string. 165 * This is only valid for single-valued attributes that have a value. 166 * 167 * @return The active value for this configuration attribute as a string. 168 * 169 * @throws ConfigException If this attribute does not have exactly one 170 * active value. 171 */ 172 public String activeValue() 173 throws ConfigException 174 { 175 if (values == null || values.isEmpty()) 176 { 177 throw new ConfigException(ERR_CONFIG_ATTR_NO_STRING_VALUE.get(getName())); 178 } 179 if (values.size() > 1) 180 { 181 throw new ConfigException(ERR_CONFIG_ATTR_MULTIPLE_STRING_VALUES.get(getName())); 182 } 183 184 return values.get(0); 185 } 186 187 188 189 /** 190 * Retrieves the set of active values for this configuration attribute. 191 * 192 * @return The set of active values for this configuration attribute. 193 */ 194 public List<String> activeValues() 195 { 196 return values; 197 } 198 199 200 201 /** 202 * Retrieves the pending value for this configuration attribute as a string. 203 * This is only valid for single-valued attributes that have a value. If this 204 * attribute does not have any pending values, then the active value will be 205 * returned. 206 * 207 * @return The pending value for this configuration attribute as a string. 208 * 209 * @throws ConfigException If this attribute does not have exactly one 210 * pending value. 211 */ 212 public String pendingValue() 213 throws ConfigException 214 { 215 return activeValue(); 216 } 217 218 219 220 /** 221 * Retrieves the set of pending values for this configuration attribute. If 222 * there are no pending values, then the set of active values will be 223 * returned. 224 * 225 * @return The set of pending values for this configuration attribute. 226 */ 227 public List<String> pendingValues() 228 { 229 return activeValues(); 230 } 231 232 233 234 /** 235 * Sets the value for this string configuration attribute. 236 * 237 * @param value The value for this string configuration attribute. 238 * 239 * @throws ConfigException If the provided value is not acceptable. 240 */ 241 public void setValue(String value) throws ConfigException 242 { 243 throw new ConfigException(ERR_CONFIG_ATTR_READ_ONLY.get(getName())); 244 } 245 246 247 248 /** 249 * Sets the values for this string configuration attribute. 250 * 251 * @param values The set of values for this string configuration attribute. 252 * 253 * @throws ConfigException If the provided value set or any of the 254 * individual values are not acceptable. 255 */ 256 public void setValues(List<String> values) throws ConfigException 257 { 258 throw new ConfigException(ERR_CONFIG_ATTR_READ_ONLY.get(getName())); 259 } 260 261 262 263 /** 264 * Applies the set of pending values, making them the active values for this 265 * configuration attribute. This will not take any action if there are no 266 * pending values. 267 */ 268 public void applyPendingValues() 269 { 270 } 271 272 273 274 /** 275 * Indicates whether the provided value is acceptable for use in this 276 * attribute. If it is not acceptable, then the reason should be written into 277 * the provided buffer. 278 * 279 * @param value The value for which to make the determination. 280 * @param rejectReason A buffer into which a human-readable reason for the 281 * reject may be written. 282 * 283 * @return <CODE>true</CODE> if the provided value is acceptable for use in 284 * this attribute, or <CODE>false</CODE> if not. 285 */ 286 public boolean valueIsAcceptable(ByteString value, StringBuilder rejectReason) 287 { 288 rejectReason.append(ERR_CONFIG_ATTR_READ_ONLY.get(getName())); 289 return false; 290 } 291 292 293 294 /** 295 * Converts the provided set of strings to a corresponding set of attribute 296 * values. 297 * 298 * @param valueStrings The set of strings to be converted into attribute 299 * values. 300 * @param allowFailures Indicates whether the decoding process should allow 301 * any failures in which one or more values could be 302 * decoded but at least one could not. If this is 303 * <CODE>true</CODE> and such a condition is acceptable 304 * for the underlying attribute type, then the returned 305 * set of values should simply not include those 306 * undecodable values. 307 * 308 * @return The set of attribute values converted from the provided strings. 309 * 310 * @throws ConfigException If an unrecoverable problem occurs while 311 * performing the conversion. 312 */ 313 public LinkedHashSet<ByteString> stringsToValues(List<String> valueStrings, boolean allowFailures) 314 throws ConfigException 315 { 316 if (valueStrings == null || valueStrings.isEmpty()) 317 { 318 return new LinkedHashSet<>(); 319 } 320 return getValueSet(valueStrings); 321 } 322 323 /** 324 * Converts the set of active values for this configuration attribute into a 325 * set of strings that may be stored in the configuration or represented over 326 * protocol. The string representation used by this method should be 327 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 328 * method. 329 * 330 * @return The string representations of the set of active values for this 331 * configuration attribute. 332 */ 333 public List<String> activeValuesToStrings() 334 { 335 return values; 336 } 337 338 339 340 /** 341 * Converts the set of pending values for this configuration attribute into a 342 * set of strings that may be stored in the configuration or represented over 343 * protocol. The string representation used by this method should be 344 * compatible with the decoding used by the <CODE>stringsToValues</CODE> 345 * method. 346 * 347 * @return The string representations of the set of pending values for this 348 * configuration attribute, or <CODE>null</CODE> if there are no 349 * pending values. 350 */ 351 public List<String> pendingValuesToStrings() 352 { 353 return activeValuesToStrings(); 354 } 355 356 357 358 /** 359 * Retrieves a new configuration attribute of this type that will contain the 360 * values from the provided attribute. 361 * 362 * @param attributeList The list of attributes to use to create the config 363 * attribute. The list must contain either one or two 364 * elements, with both attributes having the same base 365 * name and the only option allowed is ";pending" and 366 * only if this attribute is one that requires admin 367 * action before a change may take effect. 368 * 369 * @return The generated configuration attribute. 370 * 371 * @throws ConfigException If the provided attribute cannot be treated as a 372 * configuration attribute of this type (e.g., if 373 * one or more of the values of the provided 374 * attribute are not suitable for an attribute of 375 * this type, or if this configuration attribute is 376 * single-valued and the provided attribute has 377 * multiple values). 378 */ 379 public ConfigAttribute getConfigAttribute(List<Attribute> attributeList) 380 throws ConfigException 381 { 382 // The attribute won't be present in the entry, so we'll just return a 383 // reference to this attribute. 384 return duplicate(); 385 } 386 387 388 389 /** 390 * Retrieves a JMX attribute containing the active value set for this 391 * configuration attribute. 392 * 393 * @return A JMX attribute containing the active value set for this 394 * configuration attribute, or <CODE>null</CODE> if it does not have 395 * any active values. 396 */ 397 public javax.management.Attribute toJMXAttribute() 398 { 399 if (isMultiValued()) 400 { 401 String[] valueArray = values.toArray(new String[values.size()]); 402 return new javax.management.Attribute(getName(), valueArray); 403 } 404 else if (!values.isEmpty()) 405 { 406 return new javax.management.Attribute(getName(), values.get(0)); 407 } 408 else 409 { 410 return null; 411 } 412 } 413 414 /** 415 * Retrieves a JMX attribute containing the pending value set for this 416 * configuration attribute. As this an read only attribute, this method 417 * should never be called 418 * 419 * @return A JMX attribute containing the pending value set for this 420 * configuration attribute, or <CODE>null</CODE> if it does 421 * not have any active values. 422 */ 423 @Override 424 public javax.management.Attribute toJMXAttributePending() 425 { 426 // Should never occur !!! 427 return toJMXAttribute(); 428 } 429 430 431 432 /** 433 * Adds information about this configuration attribute to the provided JMX 434 * attribute list. If this configuration attribute requires administrative 435 * action before changes take effect and it has a set of pending values, then 436 * two attributes should be added to the list -- one for the active value 437 * and one for the pending value. The pending value should be named with 438 * the pending option. 439 * 440 * @param attributeList The attribute list to which the JMX attribute(s) 441 * should be added. 442 */ 443 public void toJMXAttribute(AttributeList attributeList) 444 { 445 attributeList.add(toJMXAttribute()); 446 } 447 448 449 450 /** 451 * Adds information about this configuration attribute to the provided list in 452 * the form of a JMX <CODE>MBeanAttributeInfo</CODE> object. If this 453 * configuration attribute requires administrative action before changes take 454 * effect and it has a set of pending values, then two attribute info objects 455 * should be added to the list -- one for the active value (which should be 456 * read-write) and one for the pending value (which should be read-only). The 457 * pending value should be named with the pending option. 458 * 459 * @param attributeInfoList The list to which the attribute information 460 * should be added. 461 */ 462 public void toJMXAttributeInfo(List<MBeanAttributeInfo> attributeInfoList) 463 { 464 attributeInfoList.add(new MBeanAttributeInfo(getName(), getType(), 465 String.valueOf(getDescription()), true, false, false)); 466 } 467 468 469 470 /** 471 * Retrieves a JMX <CODE>MBeanParameterInfo</CODE> object that describes this 472 * configuration attribute. 473 * 474 * @return A JMX <CODE>MBeanParameterInfo</CODE> object that describes this 475 * configuration attribute. 476 */ 477 public MBeanParameterInfo toJMXParameterInfo() 478 { 479 return new MBeanParameterInfo(getName(), getType(), String.valueOf(getDescription())); 480 } 481 482 private String getType() 483 { 484 return isMultiValued() ? JMX_TYPE_STRING_ARRAY : String.class.getName(); 485 } 486 487 /** 488 * Attempts to set the value of this configuration attribute based on the 489 * information in the provided JMX attribute. 490 * 491 * @param jmxAttribute The JMX attribute to use to attempt to set the value 492 * of this configuration attribute. 493 * 494 * @throws ConfigException If the provided JMX attribute does not have an 495 * acceptable value for this configuration 496 * attribute. 497 */ 498 public void setValue(javax.management.Attribute jmxAttribute) 499 throws ConfigException 500 { 501 throw new ConfigException(ERR_CONFIG_ATTR_READ_ONLY.get(getName())); 502 } 503 504 505 506 /** 507 * Creates a duplicate of this configuration attribute. 508 * 509 * @return A duplicate of this configuration attribute. 510 */ 511 public ConfigAttribute duplicate() 512 { 513 return new ReadOnlyConfigAttribute(getName(), getDescription(), activeValues()); 514 } 515}