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}