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 2011-2014 ForgeRock AS 025 */ 026 027package org.forgerock.opendj.ldap.schema; 028 029import org.forgerock.opendj.ldap.DN; 030import org.forgerock.opendj.ldap.Entry; 031import org.forgerock.opendj.ldap.LdapException; 032 033/** 034 * This class provides various schema validation policy options for controlling 035 * how entries should be validated against the directory schema. 036 */ 037public final class SchemaValidationPolicy { 038 /** 039 * A call-back which will be called during DIT structure rule schema 040 * validation in order to retrieve the parent of the entry being validated. 041 */ 042 public static interface EntryResolver { 043 /** 044 * Returns the named entry in order to enforce DIT structure rules. 045 * 046 * @param dn 047 * The name of the entry to be returned. 048 * @return The named entry. 049 * @throws LdapException 050 * If the entry could not be retrieved. 051 */ 052 Entry getEntry(DN dn) throws LdapException; 053 } 054 055 /** 056 * An enumeration of the possible actions which can be performed when a 057 * schema validation failure is encountered. 058 */ 059 public static enum Action { 060 /** 061 * Schema validation will not be performed. 062 */ 063 IGNORE, 064 065 /** 066 * Schema validation will be performed, but failures will not cause the 067 * overall validation to fail. Error messages will be returned. 068 */ 069 WARN, 070 071 /** 072 * Schema validation will be performed and failures will cause the 073 * overall validation to fail. Error messages will be returned. 074 */ 075 REJECT; 076 077 private Action() { 078 // Nothing to do. 079 } 080 081 /** 082 * Returns {@code true} if this policy is {@code IGNORE}. 083 * 084 * @return {@code true} if this policy is {@code IGNORE}. 085 */ 086 public boolean isIgnore() { 087 return this == IGNORE; 088 } 089 090 /** 091 * Returns {@code true} if this policy is {@code REJECT}. 092 * 093 * @return {@code true} if this policy is {@code REJECT}. 094 */ 095 public boolean isReject() { 096 return this == REJECT; 097 } 098 099 /** 100 * Returns {@code true} if this policy is {@code WARN}. 101 * 102 * @return {@code true} if this policy is {@code WARN}. 103 */ 104 public boolean isWarn() { 105 return this == WARN; 106 } 107 108 /** 109 * Returns {@code true} if this policy is {@code WARN} or {@code REJECT} 110 * . 111 * 112 * @return {@code true} if this policy is {@code WARN} or {@code REJECT} 113 * . 114 */ 115 public boolean needsChecking() { 116 return this != IGNORE; 117 } 118 } 119 120 /** 121 * Creates a copy of the provided schema validation policy. 122 * 123 * @param policy 124 * The policy to be copied. 125 * @return The copy of the provided schema validation policy. 126 */ 127 public static SchemaValidationPolicy copyOf(final SchemaValidationPolicy policy) { 128 return defaultPolicy().assign(policy); 129 } 130 131 /** 132 * Creates a new schema validation policy with default settings. More 133 * specifically: 134 * <ul> 135 * <li>Entries not having a single structural object class will be rejected 136 * <li>Entries having attributes which are not permitted by its object 137 * classes or DIT content rule (if present) will be rejected 138 * <li>Entries not conforming to name forms will be rejected 139 * <li>DIT structure rules will not be ignored 140 * </ul> 141 * 142 * @return The new schema validation policy. 143 */ 144 public static SchemaValidationPolicy defaultPolicy() { 145 return new SchemaValidationPolicy(); 146 } 147 148 /** 149 * Creates a new schema validation policy which will not perform any schema 150 * validation. 151 * 152 * @return The new schema validation policy. 153 */ 154 public static SchemaValidationPolicy ignoreAll() { 155 return new SchemaValidationPolicy().checkAttributesAndObjectClasses(Action.IGNORE) 156 .checkAttributeValues(Action.IGNORE).checkDITContentRules(Action.IGNORE) 157 .checkNameForms(Action.IGNORE).requireSingleStructuralObjectClass(Action.IGNORE); 158 } 159 160 private Action checkNameForms = Action.REJECT; 161 private Action checkDITStructureRules = Action.IGNORE; 162 private Action checkDITContentRules = Action.REJECT; 163 private Action requireSingleStructuralObjectClass = Action.REJECT; 164 private Action checkAttributesAndObjectClasses = Action.REJECT; 165 private Action checkAttributeValues = Action.REJECT; 166 private EntryResolver checkDITStructureRulesEntryResolver; 167 168 /** Prevent direct instantiation. */ 169 private SchemaValidationPolicy() { 170 // Nothing to do. 171 } 172 173 /** 174 * Returns the policy for verifying that the user attributes in an entry 175 * conform to its object classes. More specifically, an entry must contain 176 * all required user attributes, and must not contain any user attributes 177 * which are not declared as required or optional by its object classes. 178 * <p> 179 * By default entries which have missing or additional user attributes will 180 * be rejected. 181 * 182 * @return The policy for verifying that the user attributes in an entry 183 * conform to its object classes. 184 */ 185 public Action checkAttributesAndObjectClasses() { 186 return checkAttributesAndObjectClasses; 187 } 188 189 /** 190 * Specifies the policy for verifying that the user attributes in an entry 191 * conform to its object classes. More specifically, an entry must contain 192 * all required user attributes, and must not contain any user attributes 193 * which are not declared as required or optional by its object classes. 194 * <p> 195 * By default entries which have missing or additional user attributes will 196 * be rejected. 197 * 198 * @param policy 199 * The policy for verifying that the user attributes in an entry 200 * conform to its object classes. 201 * @return A reference to this {@code SchemaValidationPolicy}. 202 */ 203 public SchemaValidationPolicy checkAttributesAndObjectClasses(final Action policy) { 204 this.checkAttributesAndObjectClasses = policy; 205 return this; 206 } 207 208 /** 209 * Returns the policy for verifying that the user attributes in an entry 210 * conform to their associated attribute type descriptions. This may 211 * include: 212 * <ul> 213 * <li>checking that there is at least one value 214 * <li>checking that single-valued attributes contain only a single value 215 * <li>checking that there are no duplicate values according to the 216 * attribute's default equality matching rule 217 * <li>checking that attributes which require BER encoding specify the 218 * {@code ;binary} attribute option 219 * <li>checking that the values are valid according to the attribute's 220 * syntax. 221 * </ul> 222 * Schema validation implementations specify exactly which of the above 223 * checks will be performed. 224 * <p> 225 * By default entries which have invalid attribute values will be rejected. 226 * 227 * @return The policy for verifying that the user attributes in an entry 228 * conform to their associated attribute type descriptions. 229 */ 230 public Action checkAttributeValues() { 231 return checkAttributeValues; 232 } 233 234 /** 235 * Specifies the policy for verifying that the user attributes in an entry 236 * conform to their associated attribute type descriptions. This may 237 * include: 238 * <ul> 239 * <li>checking that there is at least one value 240 * <li>checking that single-valued attributes contain only a single value 241 * <li>checking that there are no duplicate values according to the 242 * attribute's default equality matching rule 243 * <li>checking that attributes which require BER encoding specify the 244 * {@code ;binary} attribute option 245 * <li>checking that the values are valid according to the attribute's 246 * syntax. 247 * </ul> 248 * Schema validation implementations specify exactly which of the above 249 * checks will be performed. 250 * <p> 251 * By default entries which have invalid attribute values will be rejected. 252 * 253 * @param policy 254 * The policy for verifying that the user attributes in an entry 255 * conform to their associated attribute type descriptions. 256 * @return A reference to this {@code SchemaValidationPolicy}. 257 */ 258 public SchemaValidationPolicy checkAttributeValues(final Action policy) { 259 this.checkAttributeValues = policy; 260 return this; 261 } 262 263 /** 264 * Returns the policy for validating entries against content rules defined 265 * in the schema. 266 * <p> 267 * By default content rules will be ignored during validation. 268 * 269 * @return The policy for validating entries against content rules defined 270 * in the schema. 271 */ 272 public Action checkDITContentRules() { 273 return checkDITContentRules; 274 } 275 276 /** 277 * Specifies the policy for validating entries against content rules defined 278 * in the schema. 279 * <p> 280 * By default content rules will be ignored during validation. 281 * 282 * @param policy 283 * The policy for validating entries against content rules 284 * defined in the schema. 285 * @return A reference to this {@code SchemaValidationPolicy}. 286 */ 287 public SchemaValidationPolicy checkDITContentRules(final Action policy) { 288 this.checkDITContentRules = policy; 289 return this; 290 } 291 292 /** 293 * Returns the policy for validating entries against structure rules defined 294 * in the schema. 295 * <p> 296 * By default structure rules will be ignored during validation. 297 * 298 * @return The policy for validating entries against structure rules defined 299 * in the schema. 300 */ 301 public Action checkDITStructureRules() { 302 return checkDITStructureRules; 303 } 304 305 /** 306 * Specifies the policy for validating entries against structure rules 307 * defined in the schema. 308 * <p> 309 * By default structure rules will be ignored during validation. 310 * 311 * @param policy 312 * The policy for validating entries against structure rules 313 * defined in the schema. 314 * @param resolver 315 * The parent entry resolver which should be used for retrieving 316 * the parent entry during DIT structure rule validation. 317 * @return A reference to this {@code SchemaValidationPolicy}. 318 * @throws IllegalArgumentException 319 * If {@code resolver} was {@code null} and 320 * {@code checkDITStructureRules} is either {@code WARN} or 321 * {@code REJECT}. 322 */ 323 public SchemaValidationPolicy checkDITStructureRules(final Action policy, 324 final EntryResolver resolver) { 325 if (checkDITStructureRules.needsChecking() && resolver == null) { 326 throw new IllegalArgumentException( 327 "Validation of structure rules enabled by resolver was null"); 328 } 329 this.checkDITStructureRules = policy; 330 this.checkDITStructureRulesEntryResolver = resolver; 331 return this; 332 } 333 334 /** 335 * Returns parent entry resolver which should be used for retrieving the 336 * parent entry during DIT structure rule validation. 337 * <p> 338 * By default no resolver is defined because structure rules will be ignored 339 * during validation. 340 * 341 * @return The parent entry resolver which should be used for retrieving the 342 * parent entry during DIT structure rule validation. 343 */ 344 public EntryResolver checkDITStructureRulesEntryResolver() { 345 return checkDITStructureRulesEntryResolver; 346 } 347 348 /** 349 * Returns the policy for validating entries against name forms defined in 350 * the schema. 351 * <p> 352 * By default name forms will be ignored during validation. 353 * 354 * @return The policy for validating entries against name forms defined in 355 * the schema. 356 */ 357 public Action checkNameForms() { 358 return checkNameForms; 359 } 360 361 /** 362 * Specifies the policy for validating entries against name forms defined in 363 * the schema. 364 * <p> 365 * By default name forms will be ignored during validation. 366 * 367 * @param policy 368 * The policy for validating entries against name forms defined 369 * in the schema. 370 * @return A reference to this {@code SchemaValidationPolicy}. 371 */ 372 public SchemaValidationPolicy checkNameForms(final Action policy) { 373 this.checkNameForms = policy; 374 return this; 375 } 376 377 /** 378 * Returns the policy for verifying that entries have only a single 379 * structural object class. 380 * <p> 381 * By default entries which do not have a structural object class or which 382 * have more than one structural object class will be rejected. 383 * 384 * @return The policy for checking that entries have one and only one 385 * structural object class. 386 */ 387 public Action requireSingleStructuralObjectClass() { 388 return requireSingleStructuralObjectClass; 389 } 390 391 /** 392 * Specifies the policy for verifying that entries have only a single 393 * structural object class. 394 * <p> 395 * By default entries which do not have a structural object class or which 396 * have more than one structural object class will be rejected. 397 * 398 * @param policy 399 * The policy for checking that entries have one and only one 400 * structural object class. 401 * @return A reference to this {@code SchemaValidationPolicy}. 402 */ 403 public SchemaValidationPolicy requireSingleStructuralObjectClass(final Action policy) { 404 this.requireSingleStructuralObjectClass = policy; 405 return this; 406 } 407 408 /** 409 * Returns a strict view of the provided schema if the this policy is 410 * configured to check attributes and object class, or a non-strict view of 411 * the schema if not. 412 * 413 * @param schema 414 * The schema to be adapted according to this policy. 415 * @return A strict or non-strict view of {@code schema} depending on 416 * {@link #checkAttributesAndObjectClasses()}. 417 */ 418 public Schema adaptSchemaForValidation(final Schema schema) { 419 return checkAttributesAndObjectClasses().needsChecking() ? schema.asStrictSchema() : schema 420 .asNonStrictSchema(); 421 } 422 423 /** Assigns the provided options to this set of options. */ 424 SchemaValidationPolicy assign(final SchemaValidationPolicy policy) { 425 this.checkAttributeValues = policy.checkAttributeValues; 426 this.checkNameForms = policy.checkNameForms; 427 this.checkAttributesAndObjectClasses = policy.checkAttributesAndObjectClasses; 428 this.checkDITContentRules = policy.checkDITContentRules; 429 this.checkDITStructureRules = policy.checkDITStructureRules; 430 this.checkDITStructureRulesEntryResolver = policy.checkDITStructureRulesEntryResolver; 431 this.requireSingleStructuralObjectClass = policy.requireSingleStructuralObjectClass; 432 return this; 433 } 434 435}