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-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017package org.opends.server.types;
018
019import static org.forgerock.util.Reject.*;
020import static org.opends.messages.SchemaMessages.*;
021import static org.opends.server.util.CollectionUtils.*;
022import static org.opends.server.util.ServerConstants.*;
023
024import java.util.List;
025import java.util.Map;
026
027import org.forgerock.i18n.LocalizableMessage;
028import org.forgerock.opendj.ldap.ResultCode;
029import org.forgerock.opendj.ldap.schema.SchemaElement;
030import org.opends.server.util.RemoveOnceSDKSchemaIsUsed;
031
032/**
033 * Utility class to retrieve information from a SchemaElement and to set extra property
034 * for a SchemaElement.
035 * <p>
036 * Note that {@code setSchemaFile()} method works ONLY for non-SDK classes, because SDK schema
037 * elements are immutable, so modifying the map for extra properties has no effect on the actual
038 * element.
039 */
040@RemoveOnceSDKSchemaIsUsed("All read methods can be provided by ServerSchemaElement class. Write method" +
041 " has to rebuild fully the schema element within the schema, which means specific code for each element")
042public final class CommonSchemaElements
043{
044  private CommonSchemaElements()
045  {
046    // private for utility classes
047  }
048
049  /**
050   * Check if the extra schema properties contain safe filenames.
051   *
052   * @param extraProperties
053   *          The schema properties to check.
054   *
055   * @throws DirectoryException
056   *          If a provided value was unsafe.
057   */
058  public static void checkSafeProperties(Map <String,List<String>>
059      extraProperties)
060      throws DirectoryException
061  {
062    // Check that X-SCHEMA-FILE doesn't contain unsafe characters
063    List<String> filenames = extraProperties.get(SCHEMA_PROPERTY_FILENAME);
064    if (filenames != null && !filenames.isEmpty()) {
065      String filename = filenames.get(0);
066      if (filename.indexOf('/') != -1 || filename.indexOf('\\') != -1)
067      {
068        LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_X_SCHEMA_FILE.get(filename);
069        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
070            message);
071      }
072    }
073  }
074
075  /**
076   * Retrieves the name of the schema file that contains the
077   * definition for this schema definition.
078   *
079   * @param elem The element where to get the schema file from
080   * @return The name of the schema file that contains the definition
081   *         for this schema definition, or <code>null</code> if it
082   *         is not known or if it is not stored in any schema file.
083   */
084  public static String getSchemaFile(SchemaElement elem)
085  {
086    return getSingleValueProperty(elem, SCHEMA_PROPERTY_FILENAME);
087  }
088
089  /**
090   * Retrieves the name of a single value property for this schema element.
091   *
092   * @param elem The element where to get the single value property from
093   * @param propertyName The name of the property to get
094   * @return The single value for this property, or <code>null</code> if it
095   *         is this property is not set.
096   */
097  public static String getSingleValueProperty(SchemaElement elem,
098      String propertyName)
099  {
100    List<String> values = elem.getExtraProperties().get(propertyName);
101    if (values != null && !values.isEmpty()) {
102      return values.get(0);
103    }
104    return null;
105  }
106
107  /**
108   * Specifies the name of the schema file that contains the
109   * definition for this schema element.  If a schema file is already
110   * defined in the set of extra properties, then it will be
111   * overwritten.  If the provided schema file value is {@code null},
112   * then any existing schema file definition will be removed.
113   *
114   * @param elem The element where to set the schema file
115   * @param  schemaFile  The name of the schema file that contains the
116   *                     definition for this schema element.
117   */
118  public static void setSchemaFile(SchemaElement elem, String schemaFile)
119  {
120    setExtraProperty(elem, SCHEMA_PROPERTY_FILENAME, schemaFile);
121  }
122
123  /**
124   * Sets the value for an "extra" property for this schema element.
125   * If a property already exists with the specified name, then it
126   * will be overwritten.  If the value is {@code null}, then any
127   * existing property with the given name will be removed.
128   *
129   * @param elem The element where to set the extra property
130   * @param  name   The name for the "extra" property.  It must not be
131   *                {@code null}.
132   * @param  value  The value for the "extra" property.  If it is
133   *                {@code null}, then any existing definition will be removed.
134   */
135  private static void setExtraProperty(SchemaElement elem, String name, String value)
136  {
137    ifNull(name);
138
139    if (value == null)
140    {
141      elem.getExtraProperties().remove(name);
142    }
143    else
144    {
145      elem.getExtraProperties().put(name, newLinkedList(value));
146    }
147  }
148
149  /**
150   * Retrieves the definition string used to create this attribute
151   * type and including the X-SCHEMA-FILE extension.
152   *
153   * @param elem The element where to get definition from
154   * @return  The definition string used to create this attribute
155   *          type including the X-SCHEMA-FILE extension.
156   */
157  public static String getDefinitionWithFileName(SchemaElement elem)
158  {
159    final String definition = elem.toString();
160    return Schema.addSchemaFileToElementDefinitionIfAbsent(definition, getSchemaFile(elem));
161  }
162}