2624N/A/*
2624N/A * CDDL HEADER START
2624N/A *
2624N/A * The contents of this file are subject to the terms of the
2624N/A * Common Development and Distribution License, Version 1.0 only
2624N/A * (the "License"). You may not use this file except in compliance
2624N/A * with the License.
2624N/A *
2624N/A * You can obtain a copy of the license at
2624N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE
2624N/A * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
2624N/A * See the License for the specific language governing permissions
2624N/A * and limitations under the License.
2624N/A *
2624N/A * When distributing Covered Code, include this CDDL HEADER in each
2624N/A * file and include the License file at
2624N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
2624N/A * add the following below this CDDL HEADER, with the fields enclosed
2624N/A * by brackets "[]" replaced with your own identifying information:
2624N/A * Portions Copyright [yyyy] [name of copyright owner]
2624N/A *
2624N/A * CDDL HEADER END
2624N/A *
2624N/A *
3215N/A * Copyright 2008 Sun Microsystems, Inc.
5472N/A * Portions copyright 2011 ForgeRock AS
2624N/A */
2624N/Apackage org.opends.server.admin;
2624N/A
2624N/Aimport static org.opends.server.util.ServerConstants.*;
2624N/A
2624N/Aimport java.util.ArrayList;
2624N/Aimport java.util.Arrays;
2624N/Aimport java.util.Collection;
2624N/Aimport java.util.HashSet;
2624N/Aimport java.util.List;
2624N/Aimport java.util.Set;
2624N/A
2624N/Aimport org.opends.server.DirectoryServerTestCase;
2624N/Aimport org.opends.server.TestCaseUtils;
2624N/Aimport org.opends.server.core.DirectoryServer;
2624N/Aimport org.opends.server.types.AttributeType;
2624N/Aimport org.opends.server.types.ObjectClass;
2624N/Aimport org.opends.server.types.Schema;
2624N/Aimport org.testng.Assert;
2624N/Aimport org.testng.annotations.BeforeClass;
2624N/Aimport org.testng.annotations.DataProvider;
2624N/Aimport org.testng.annotations.Test;
2624N/A
2624N/A
2624N/Apublic class ValidateConfigDefinitionsTest extends DirectoryServerTestCase {
2624N/A
2624N/A @BeforeClass
2624N/A public void startServer() throws Exception {
2624N/A TestCaseUtils.startServer();
2624N/A }
2624N/A
2624N/A /**
2624N/A * Returns all AbstractManagedObjectDefinition objects that are
2624N/A * defined in
2624N/A */
2624N/A @DataProvider
2624N/A public Object[][] enumrateManageObjectDefns() throws Exception {
2624N/A TopCfgDefn topCfgDefn = TopCfgDefn.getInstance();
2624N/A List<AbstractManagedObjectDefinition<?,?>> allCfgDefns =
2624N/A new ArrayList<AbstractManagedObjectDefinition<?,?>>(topCfgDefn.getAllChildren());
2624N/A
2624N/A Object[][] params = new Object[allCfgDefns.size()][];
2624N/A for (int i = 0; i < params.length; i++) {
2624N/A params[i] = new Object[]{allCfgDefns.get(i)};
2624N/A }
2624N/A
2624N/A return params;
2624N/A }
2624N/A
2624N/A // Exceptions to config objects having a differnt objectclass
2624N/A private static final List<String> CLASS_OBJECT_CLASS_EXCEPTIONS =
2624N/A Arrays.asList(new String[]{
2624N/A "org.opends.server.admin.std.meta.RootCfgDefn",
2624N/A "org.opends.server.admin.std.meta.GlobalCfgDefn",
2624N/A });
2624N/A
2624N/A
2624N/A @Test(dataProvider="enumrateManageObjectDefns")
2624N/A public void validateConfigObjectDefinitions(AbstractManagedObjectDefinition<?, ?> objectDef) {
2624N/A String objName = objectDef.getName();
5472N/A StringBuilder errors = new StringBuilder();
2624N/A Collection<PropertyDefinition<?>> allDefinitions =
2624N/A objectDef.getAllPropertyDefinitions();
2624N/A
2624N/A LDAPProfile ldapProfile = LDAPProfile.getInstance();
2624N/A String ldapObjectclassName = ldapProfile.getObjectClass(objectDef);
2624N/A if (ldapObjectclassName == null) {
2624N/A errors.append("There is no objectclass definition for configuration object " + objName);
2624N/A } else {
2624N/A String expectedObjectClass = "ds-cfg-" + objName;
2624N/A if (!ldapObjectclassName.equals(expectedObjectClass) &&
2624N/A !CLASS_OBJECT_CLASS_EXCEPTIONS.contains(objectDef.getClass().getName())) {
2624N/A errors.append("For config object " + objName +
2624N/A ", the LDAP objectclass must be " + expectedObjectClass +
2624N/A " instead of " + ldapObjectclassName).append(EOL + EOL);
2624N/A }
2624N/A }
2624N/A ObjectClass configObjectClass = DirectoryServer.getSchema().getObjectClass(ldapObjectclassName.toLowerCase());;
2624N/A
5472N/A for (PropertyDefinition<?> propDef: allDefinitions) {
2624N/A validatePropertyDefinition(objectDef, configObjectClass, propDef, errors);
2624N/A }
2624N/A
2624N/A if (errors.length() > 0) {
2624N/A Assert.fail("The configuration definition for " + objectDef.getName() + " has the following problems: " + EOL +
2624N/A errors.toString());
2624N/A }
2624N/A }
2624N/A
2624N/A // Exceptions to properties ending in -class being exactly 'java-class'.
2624N/A private static final List<String> CLASS_PROPERTY_EXCEPTIONS =
2624N/A Arrays.asList(new String[]{
2624N/A // e.g. "prop-name-ending-with-class"
2624N/A });
2624N/A
2624N/A // Exceptions to properties ending in -enabled being exactly 'enabled'.
2624N/A private static final List<String> ENABLED_PROPERTY_EXCEPTIONS =
2624N/A Arrays.asList(new String[]{
5472N/A "index-filter-analyzer-enabled",
5472N/A "subordinate-indexes-enabled"
2624N/A // e.g. "prop-name-ending-with-enabled"
2624N/A });
2624N/A
2624N/A // Exceptions to properties not starting with the name of their config object
2624N/A private static final List<String> OBJECT_PREFIX_PROPERTY_EXCEPTIONS =
2624N/A Arrays.asList(new String[]{
2624N/A "backend-id",
2624N/A "plugin-type",
2624N/A "replication-server-id",
2800N/A "network-group-id",
2800N/A "workflow-id",
2800N/A "workflow-element-id",
2800N/A "workflow-element"
2624N/A // e.g. "prop-name-starting-with-object-prefix"
2624N/A });
2624N/A
2624N/A
2624N/A private void validatePropertyDefinition(AbstractManagedObjectDefinition<?, ?> objectDef,
2624N/A ObjectClass configObjectClass,
2624N/A PropertyDefinition<?> propDef,
2624N/A StringBuilder errors) {
2624N/A String objName = objectDef.getName();
2624N/A String propName = propDef.getName();
2624N/A
2624N/A // We want class properties to be exactly java-class
2624N/A if (propName.endsWith("-class") &&
2624N/A !propName.equals("java-class") &&
2624N/A !CLASS_PROPERTY_EXCEPTIONS.contains(propName))
2624N/A {
2624N/A errors.append("The " + propName + " property on config object " + objName +
2624N/A " should probably be java-class. If not, then add " +
2624N/A propName + " to the CLASS_PROPERTY_EXCEPTIONS array in " +
2624N/A ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
2624N/A " this warning.");
2624N/A }
2624N/A
2624N/A // We want enabled properties to be exactly enabled
2624N/A if (propName.endsWith("-enabled") && !ENABLED_PROPERTY_EXCEPTIONS.contains(propName))
2624N/A {
2624N/A errors.append("The " + propName + " property on config object " + objName +
2624N/A " should probably be just 'enabled'. If not, then add " +
2624N/A propName + " to the ENABLED_PROPERTY_EXCEPTIONS array in " +
2624N/A ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
2624N/A " this warning.");
2624N/A }
2624N/A
2624N/A // It's redundant for properties to be prefixed with the name of their objecty
5472N/A if (propName.startsWith(objName) && !propName.equals(objName) &&
2624N/A !OBJECT_PREFIX_PROPERTY_EXCEPTIONS.contains(propName))
2624N/A {
2624N/A errors.append("The " + propName + " property on config object " + objName +
2624N/A " should not be prefixed with the name of the config object because" +
2624N/A " this is redundant. If you disagree, then add " +
2624N/A propName + " to the OBJECT_PREFIX_PROPERTY_EXCEPTIONS array in " +
2624N/A ValidateConfigDefinitionsTest.class.getName() + " to suppress" +
2624N/A " this warning.");
2624N/A }
2624N/A
2624N/A
2624N/A LDAPProfile ldapProfile = LDAPProfile.getInstance();
2624N/A String ldapAttrName = ldapProfile.getAttributeName(objectDef, propDef);
2624N/A
2624N/A // LDAP attribute name is consistent with the property name
2624N/A String expectedLdapAttr = "ds-cfg-" + propName;
2624N/A if (!ldapAttrName.equals(expectedLdapAttr)) {
2624N/A errors.append("For the " + propName + " property on config object " + objName +
2624N/A ", the LDAP attribute must be " + expectedLdapAttr + " instead of " + ldapAttrName).append(EOL + EOL);
2624N/A }
2624N/A
2624N/A
2624N/A Schema schema = DirectoryServer.getSchema();
2624N/A AttributeType attrType = schema.getAttributeType(ldapAttrName.toLowerCase());
2624N/A
2624N/A // LDAP attribute exists
2624N/A if (attrType == null) {
2624N/A errors.append(propName + " property on config object " + objName + " is declared" +
2624N/A " to use ldap attribute " + ldapAttrName + ", but this attribute is not in the schema ").append(EOL + EOL);
2624N/A } else {
2624N/A
2624N/A // LDAP attribute is multivalued if the property is multivalued
2624N/A if (propDef.hasOption(PropertyOption.MULTI_VALUED) && attrType.isSingleValue()) {
2624N/A errors.append(propName + " property on config object " + objName + " is declared" +
2624N/A " as multi-valued, but the corresponding ldap attribute " + ldapAttrName +
2624N/A " is declared as single-valued.").append(EOL + EOL);
2624N/A }
2624N/A
2624N/A if (configObjectClass != null) {
2624N/A // If it's mandatory in the schema, it must be mandatory on the config property
2624N/A Set<AttributeType> mandatoryAttributes = configObjectClass.getRequiredAttributeChain();
2624N/A if (mandatoryAttributes.contains(attrType) && !propDef.hasOption(PropertyOption.MANDATORY)) {
2624N/A errors.append(propName + " property on config object " + objName + " is not declared" +
2624N/A " as mandatory even though the corresponding ldap attribute " + ldapAttrName +
2624N/A " is declared as mandatory in the schema.").append(EOL + EOL);
2624N/A }
2624N/A
2624N/A Set<AttributeType> allowedAttributes = new HashSet<AttributeType>(mandatoryAttributes);
2624N/A allowedAttributes.addAll(configObjectClass.getOptionalAttributeChain());
2624N/A if (!allowedAttributes.contains(attrType)) {
2624N/A errors.append(propName + " property on config object " + objName + " has" +
2624N/A " the corresponding ldap attribute " + ldapAttrName +
2624N/A ", but this attribute is not an allowed attribute on the configuration " +
2624N/A " object's objectclass " + configObjectClass.getNameOrOID()).append(EOL + EOL);
2624N/A }
2624N/A }
2624N/A }
2624N/A }
2624N/A
2624N/A
2624N/A
2624N/A}