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