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