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