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}