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 2009-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027package org.opends.server.types; 028 029import java.util.ArrayList; 030import java.util.LinkedHashSet; 031import java.util.List; 032import java.util.Set; 033 034import org.forgerock.i18n.LocalizableMessage; 035import org.forgerock.opendj.ldap.ByteString; 036import org.forgerock.opendj.ldap.ResultCode; 037import org.opends.server.core.DirectoryServer; 038 039import static org.opends.messages.SchemaMessages.*; 040import static org.opends.server.util.ServerConstants.*; 041 042/** 043 * This class represents RFC 3672 subentries and RFC 3671 044 * collective attribute subentries objects. 045 */ 046public class SubEntry { 047 /** 048 * Defines the set of permissible values for the conflict behavior. 049 * Specifies the behavior that the server is to exhibit for entries 050 * that already contain one or more real values for the associated 051 * collective attribute. 052 */ 053 public static enum CollectiveConflictBehavior { 054 /** 055 * Indicates that the virtual attribute provider is to preserve 056 * any real values contained in the entry and merge them with the 057 * set of generated virtual values so that both the real and 058 * virtual values are used. 059 */ 060 MERGE_REAL_AND_VIRTUAL("merge-real-and-virtual"), 061 062 /** 063 * Indicates that any real values contained in the entry are 064 * preserved and used, and virtual values are not generated. 065 */ 066 REAL_OVERRIDES_VIRTUAL("real-overrides-virtual"), 067 068 /** 069 * Indicates that the virtual attribute provider suppresses any 070 * real values contained in the entry and generates virtual values 071 * and uses them. 072 */ 073 VIRTUAL_OVERRIDES_REAL("virtual-overrides-real"); 074 075 /** String representation of the value. */ 076 private final String name; 077 078 /** 079 * Private constructor. 080 * @param name for this conflict behavior. 081 */ 082 private CollectiveConflictBehavior(String name) 083 { 084 this.name = name; 085 } 086 087 /** {@inheritDoc} */ 088 @Override 089 public String toString() 090 { 091 return name; 092 } 093 } 094 095 /** 096 * The name of the "collectiveConflictBehavior" attribute type, 097 * formatted in all lowercase characters. 098 */ 099 public static final String ATTR_COLLECTIVE_CONFLICT_BEHAVIOR = 100 "collectiveconflictbehavior"; 101 102 /** 103 * The name of the "inheritFromDNAttribute" attribute type, 104 * formatted in all lowercase characters. 105 */ 106 public static final String ATTR_INHERIT_COLLECTIVE_FROM_DN = 107 "inheritfromdnattribute"; 108 109 /** 110 * The name of the "inheritFromRDNAttribute" attribute type, 111 * formatted in all lowercase characters. 112 */ 113 public static final String ATTR_INHERIT_COLLECTIVE_FROM_RDN = 114 "inheritfromrdnattribute"; 115 116 /** 117 * The name of the "inheritFromRDNType" attribute type, 118 * formatted in all lowercase characters. 119 */ 120 public static final String ATTR_INHERIT_COLLECTIVE_FROM_RDN_TYPE = 121 "inheritfromrdntype"; 122 123 /** 124 * The name of the "inheritFromBaseRDN" attribute type, 125 * formatted in all lowercase characters. 126 */ 127 public static final String ATTR_INHERIT_COLLECTIVE_FROM_BASE = 128 "inheritfrombaserdn"; 129 130 /** 131 * The name of the "inheritAttribute" attribute type, 132 * formatted in all lowercase characters. 133 */ 134 public static final String ATTR_INHERIT_COLLECTIVE_ATTR = 135 "inheritattribute"; 136 137 /** Attribute option to mark attributes collective. */ 138 private static final String ATTR_OPTION_COLLECTIVE = 139 "collective"; 140 141 /** Entry object. */ 142 private Entry entry; 143 144 /** Subtree specification. */ 145 private SubtreeSpecification subTreeSpec; 146 147 /** Collective subentry flag. */ 148 private boolean isCollective; 149 /** Inherited collective subentry flag. */ 150 private boolean isInheritedCollective; 151 /** Inherited collective from DN subentry flag. */ 152 private boolean isInheritedFromDNCollective; 153 /** Inherited collective from RDN subentry flag. */ 154 private boolean isInheritedFromRDNCollective; 155 156 /** Inherited collective DN attribute type. */ 157 private AttributeType inheritFromDNType; 158 /** Inherited collective RDN attribute type. */ 159 private AttributeType inheritFromRDNAttrType; 160 /** Inherited collective RDN type attribute type. */ 161 private AttributeType inheritFromRDNType; 162 163 /** Inherited collective RDN attribute value. */ 164 private ByteString inheritFromRDNAttrValue; 165 /** Inherited collective from DN value. */ 166 private ByteString inheritFromDNAttrValue; 167 168 /** Inherited collective from base DN. */ 169 private DN inheritFromBaseDN; 170 171 /** Collective attributes. */ 172 private List<Attribute> collectiveAttributes; 173 174 /** Conflict behavior. */ 175 private CollectiveConflictBehavior conflictBehavior = 176 CollectiveConflictBehavior.REAL_OVERRIDES_VIRTUAL; 177 178 /** 179 * Constructs a subentry object from a given entry object. 180 * @param entry LDAP subentry to construct from. 181 * @throws DirectoryException if there is a problem with 182 * constructing a subentry from a given entry. 183 */ 184 public SubEntry(Entry entry) throws DirectoryException 185 { 186 this.entry = entry; 187 188 // Process subtree specification. 189 this.subTreeSpec = null; 190 String specString = null; 191 boolean isValidSpec = true; 192 AttributeType specAttrType = DirectoryServer.getAttributeTypeOrDefault(ATTR_SUBTREE_SPEC_LC); 193 List<Attribute> specAttrList = entry.getAttribute(specAttrType); 194 if (specAttrList != null) 195 { 196 for (Attribute attr : specAttrList) 197 { 198 for (ByteString value : attr) 199 { 200 specString = value.toString(); 201 try 202 { 203 this.subTreeSpec = SubtreeSpecification.valueOf( 204 entry.getName().parent(), specString); 205 isValidSpec = true; 206 } 207 catch (DirectoryException de) 208 { 209 isValidSpec = false; 210 } 211 if (this.subTreeSpec != null) 212 { 213 break; 214 } 215 } 216 if (this.subTreeSpec != null) 217 { 218 break; 219 } 220 } 221 } 222 223 // Check that the subtree spec is flagged as valid. If it is not 224 // that means all parsers have failed and it is invalid syntax. 225 if (!isValidSpec) 226 { 227 LocalizableMessage message = 228 ERR_ATTR_SYNTAX_SUBTREE_SPECIFICATION_INVALID.get( 229 specString); 230 throw new DirectoryException( 231 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); 232 } 233 234 // Subentry has to to have a subtree specification. 235 if (this.subTreeSpec == null) 236 { 237 // There is none for some reason eg this could be 238 // old Draft based ldapSubEntry so create a dummy. 239 this.subTreeSpec = new SubtreeSpecification(entry.getName().parent(), 240 null, -1, -1, null, null, null); 241 } 242 243 // Determine if this subentry is collective attribute subentry. 244 this.isCollective = entry.isCollectiveAttributeSubentry(); 245 246 // Determine if this subentry is inherited collective 247 // attribute subentry and if so what kind. 248 this.isInheritedCollective = 249 entry.isInheritedCollectiveAttributeSubentry(); 250 if (this.isInheritedCollective) 251 { 252 this.isInheritedFromDNCollective = 253 entry.isInheritedFromDNCollectiveAttributeSubentry(); 254 this.isInheritedFromRDNCollective = 255 entry.isInheritedFromRDNCollectiveAttributeSubentry(); 256 } 257 258 // Process collective attributes. 259 this.collectiveAttributes = new ArrayList<>(); 260 if (this.isCollective) 261 { 262 List<Attribute> subAttrList = entry.getAttributes(); 263 for (Attribute subAttr : subAttrList) 264 { 265 AttributeType attrType = subAttr.getAttributeType(); 266 if (attrType.isCollective()) 267 { 268 CollectiveVirtualAttribute collectiveAttr = 269 new CollectiveVirtualAttribute(subAttr); 270 this.collectiveAttributes.add(collectiveAttr); 271 } 272 else if (subAttr.hasOption(ATTR_OPTION_COLLECTIVE)) 273 { 274 AttributeBuilder builder = new AttributeBuilder(subAttr.getAttributeType()); 275 builder.addAll(subAttr); 276 Set<String> options = new LinkedHashSet<>(subAttr.getOptions()); 277 options.remove(ATTR_OPTION_COLLECTIVE); 278 builder.setOptions(options); 279 Attribute attr = builder.toAttribute(); 280 CollectiveVirtualAttribute collectiveAttr = new CollectiveVirtualAttribute(attr); 281 this.collectiveAttributes.add(collectiveAttr); 282 } 283 } 284 } 285 286 // Process inherited collective attributes. 287 if (this.isInheritedCollective) 288 { 289 if (this.isInheritedFromDNCollective) 290 { 291 List<Attribute> attrList = entry.getAttribute( 292 ATTR_INHERIT_COLLECTIVE_FROM_DN); 293 if (attrList != null && !attrList.isEmpty()) 294 { 295 for (Attribute attr : attrList) 296 { 297 for (ByteString value : attr) 298 { 299 this.inheritFromDNType = DirectoryServer.getAttributeTypeOrDefault(value.toString().toLowerCase()); 300 this.inheritFromDNAttrValue = value; 301 break; 302 } 303 } 304 } 305 } 306 307 if (this.isInheritedFromRDNCollective) 308 { 309 List<Attribute> attrList = entry.getAttribute(ATTR_INHERIT_COLLECTIVE_FROM_RDN); 310 if (attrList != null && !attrList.isEmpty()) 311 { 312 for (Attribute attr : attrList) 313 { 314 for (ByteString value : attr) 315 { 316 this.inheritFromRDNAttrType = DirectoryServer.getAttributeTypeOrDefault(value.toString().toLowerCase()); 317 this.inheritFromRDNAttrValue = value; 318 break; 319 } 320 } 321 } 322 attrList = entry.getAttribute(ATTR_INHERIT_COLLECTIVE_FROM_RDN_TYPE); 323 if (attrList != null && !attrList.isEmpty()) 324 { 325 for (Attribute attr : attrList) 326 { 327 for (ByteString value : attr) 328 { 329 this.inheritFromRDNType = DirectoryServer.getAttributeTypeOrDefault(value.toString().toLowerCase()); 330 break; 331 } 332 } 333 } 334 attrList = entry.getAttribute(ATTR_INHERIT_COLLECTIVE_FROM_BASE); 335 if (attrList != null && !attrList.isEmpty()) 336 { 337 for (Attribute attr : attrList) 338 { 339 for (ByteString value : attr) 340 { 341 // Has to have a parent since subentry itself 342 // cannot be a suffix entry within the server. 343 this.inheritFromBaseDN = getDN().parent().child(DN.decode(value)); 344 break; 345 } 346 } 347 } 348 } 349 350 List<Attribute> attrList = entry.getAttribute( 351 ATTR_INHERIT_COLLECTIVE_ATTR); 352 if (attrList != null && !attrList.isEmpty()) 353 { 354 for (Attribute attr : attrList) 355 { 356 for (ByteString value : attr) 357 { 358 CollectiveVirtualAttribute collectiveAttr = 359 new CollectiveVirtualAttribute( 360 Attributes.empty(value.toString())); 361 this.collectiveAttributes.add(collectiveAttr); 362 } 363 } 364 } 365 } 366 367 // Establish collective attribute conflict behavior. 368 if (this.isCollective || this.isInheritedCollective) 369 { 370 List<Attribute> attrList = entry.getAttribute( 371 ATTR_COLLECTIVE_CONFLICT_BEHAVIOR); 372 if (attrList != null && !attrList.isEmpty()) 373 { 374 for (Attribute attr : attrList) 375 { 376 for (ByteString value : attr) 377 { 378 for (CollectiveConflictBehavior behavior : 379 CollectiveConflictBehavior.values()) 380 { 381 if (behavior.toString().equals(value.toString())) 382 { 383 this.conflictBehavior = behavior; 384 break; 385 } 386 } 387 } 388 } 389 } 390 } 391 } 392 393 /** 394 * Retrieves the distinguished name for this subentry. 395 * @return The distinguished name for this subentry. 396 */ 397 public final DN getDN() 398 { 399 return this.entry.getName(); 400 } 401 402 /** 403 * Getter to retrieve the actual entry object 404 * for this subentry. 405 * @return entry object for this subentry. 406 */ 407 public final Entry getEntry() 408 { 409 return this.entry; 410 } 411 412 /** 413 * Indicates whether or not this subentry is 414 * a collective attribute subentry. 415 * @return <code>true</code> if collective, 416 * <code>false</code> otherwise. 417 */ 418 public boolean isCollective() 419 { 420 return this.isCollective; 421 } 422 423 /** 424 * Indicates whether or not this subentry is 425 * an inherited collective attribute subentry. 426 * @return <code>true</code> if inherited 427 * collective, <code>false</code> 428 * otherwise. 429 */ 430 public boolean isInheritedCollective() 431 { 432 return this.isInheritedCollective; 433 } 434 435 /** 436 * Indicates whether or not this subentry is 437 * an inherited from DN collective attribute 438 * subentry. 439 * @return <code>true</code> if inherited 440 * from DN collective, 441 * <code>false</code> otherwise. 442 */ 443 public boolean isInheritedFromDNCollective() 444 { 445 return this.isInheritedFromDNCollective; 446 } 447 448 /** 449 * Indicates whether or not this subentry is 450 * an inherited from RDN collective attribute 451 * subentry. 452 * @return <code>true</code> if inherited 453 * from RDN collective, 454 * <code>false</code> otherwise. 455 */ 456 public boolean isInheritedFromRDNCollective() 457 { 458 return this.isInheritedFromRDNCollective; 459 } 460 461 /** 462 * Getter to retrieve inheritFromDNAttribute type 463 * for inherited collective attribute subentry. 464 * @return Type of inheritFromDNAttribute or, 465 * <code>null</code> if there is none. 466 */ 467 public AttributeType getInheritFromDNType() 468 { 469 return this.inheritFromDNType; 470 } 471 472 /** 473 * Getter to retrieve inheritFromRDNAttribute type 474 * for inherited collective attribute subentry. 475 * @return Type of inheritFromRDNAttribute or, 476 * <code>null</code> if there is none. 477 */ 478 public AttributeType getInheritFromRDNAttrType() 479 { 480 return this.inheritFromRDNAttrType; 481 } 482 483 /** 484 * Getter to retrieve inheritFromRDNAttribute value 485 * for inherited collective attribute subentry. 486 * @return ByteString of inheritFromRDNAttribute 487 * or, <code>null</code> if there is none. 488 */ 489 public ByteString getInheritFromRDNAttrValue() 490 { 491 return this.inheritFromRDNAttrValue; 492 } 493 494 /** 495 * Getter to retrieve RDN type of inheritFromRDNType 496 * for inherited collective attribute subentry. 497 * @return RDN Type of inheritFromRDNAttribute or, 498 * <code>null</code> if there is none. 499 */ 500 public AttributeType getInheritFromRDNType() 501 { 502 return this.inheritFromRDNType; 503 } 504 505 /** 506 * Getter to retrieve inheritFromDNAttribute value 507 * for inherited collective attribute subentry. 508 * @return ByteString of inheritFromDNAttribute 509 * or, <code>null</code> if there is none. 510 */ 511 public ByteString getInheritFromDNAttrValue() 512 { 513 return this.inheritFromDNAttrValue; 514 } 515 516 /** 517 * Getter to retrieve inheritFromBaseRDN DN 518 * for inherited collective attribute subentry. 519 * @return DN of inheritFromBaseRDN or, 520 * <code>null</code> if there is none. 521 */ 522 public DN getInheritFromBaseDN() 523 { 524 return this.inheritFromBaseDN; 525 } 526 527 /** 528 * Getter for subentry subtree specification. 529 * @return subtree specification for this subentry. 530 */ 531 public SubtreeSpecification getSubTreeSpecification() 532 { 533 return this.subTreeSpec; 534 } 535 536 /** 537 * Getter for collective attributes contained within this subentry. 538 * @return collective attributes contained within this subentry. 539 */ 540 public List<Attribute> getCollectiveAttributes() 541 { 542 return this.collectiveAttributes; 543 } 544 545 /** 546 * Getter for collective conflict behavior defined for this 547 * collective attributes subentry. 548 * @return conflict behavior for this collective attributes 549 * subentry. 550 */ 551 public CollectiveConflictBehavior getConflictBehavior() 552 { 553 return this.conflictBehavior; 554 } 555}