001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.directory.server.core.api.entry; 020 021 022import java.util.ArrayList; 023import java.util.HashSet; 024import java.util.List; 025import java.util.NoSuchElementException; 026import java.util.Set; 027 028import javax.naming.NamingEnumeration; 029import javax.naming.NamingException; 030import javax.naming.directory.Attributes; 031import javax.naming.directory.BasicAttribute; 032import javax.naming.directory.BasicAttributes; 033import javax.naming.directory.DirContext; 034import javax.naming.directory.ModificationItem; 035import javax.naming.directory.SearchResult; 036 037import org.apache.directory.api.ldap.model.constants.SchemaConstants; 038import org.apache.directory.api.ldap.model.entry.Attribute; 039import org.apache.directory.api.ldap.model.entry.DefaultAttribute; 040import org.apache.directory.api.ldap.model.entry.DefaultEntry; 041import org.apache.directory.api.ldap.model.entry.DefaultModification; 042import org.apache.directory.api.ldap.model.entry.Entry; 043import org.apache.directory.api.ldap.model.entry.Modification; 044import org.apache.directory.api.ldap.model.entry.ModificationOperation; 045import org.apache.directory.api.ldap.model.entry.Value; 046import org.apache.directory.api.ldap.model.exception.LdapException; 047import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeTypeException; 048import org.apache.directory.api.ldap.model.name.Dn; 049import org.apache.directory.api.ldap.model.schema.AttributeType; 050import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions; 051import org.apache.directory.api.ldap.model.schema.SchemaManager; 052import org.apache.directory.api.ldap.model.schema.SchemaUtils; 053import org.apache.directory.api.util.EmptyEnumeration; 054import org.apache.directory.api.util.Strings; 055import org.apache.directory.server.core.api.interceptor.context.FilteringOperationContext; 056import org.apache.directory.server.i18n.I18n; 057 058 059/** 060 * A helper class used to manipulate Entries, Attributes and Values. 061 * 062 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 063 */ 064public final class ServerEntryUtils 065{ 066 private ServerEntryUtils() 067 { 068 } 069 070 071 /** 072 * Convert a ServerAttribute into a BasicAttribute. The Dn is lost 073 * during this conversion, as the Attributes object does not store 074 * this element. 075 * 076 * @param entryAttribute The Server entry to convert 077 * @return An instance of a AttributesImpl() object 078 */ 079 public static javax.naming.directory.Attribute toBasicAttribute( Attribute entryAttribute ) 080 { 081 AttributeType attributeType = entryAttribute.getAttributeType(); 082 083 javax.naming.directory.Attribute attribute = new BasicAttribute( attributeType.getName() ); 084 085 for ( Value value : entryAttribute ) 086 { 087 if ( attributeType.isHR() ) 088 { 089 attribute.add( value.getString() ); 090 } 091 else 092 { 093 attribute.add( value.getBytes() ); 094 } 095 } 096 097 return attribute; 098 } 099 100 101 /** 102 * Convert a ServerEntry into a BasicAttributes. The Dn is lost 103 * during this conversion, as the Attributes object does not store 104 * this element. 105 * 106 * @param entry The entry to convert 107 * @return An instance of a AttributesImpl() object 108 */ 109 public static Attributes toBasicAttributes( Entry entry ) 110 { 111 if ( entry == null ) 112 { 113 return null; 114 } 115 116 Attributes attributes = new BasicAttributes( true ); 117 118 for ( Attribute attribute : entry.getAttributes() ) 119 { 120 AttributeType attributeType = attribute.getAttributeType(); 121 Attribute attr = entry.get( attributeType ); 122 123 // Deal with a special case : an entry without any ObjectClass 124 if ( attributeType.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) && attr.size() == 0 ) 125 { 126 // We don't have any objectClass, just dismiss this element 127 continue; 128 } 129 130 attributes.put( toBasicAttribute( attr ) ); 131 } 132 133 return attributes; 134 } 135 136 137 /** 138 * Convert a BasicAttribute or a AttributeImpl to a ServerAtribute 139 * 140 * @param attribute the BasicAttributes or AttributesImpl instance to convert 141 * @param attributeType The AttributeType to use 142 * @return An instance of a ServerEntry object 143 * 144 * @throws LdapException If we had an incorrect attribute 145 */ 146 public static Attribute toServerAttribute( javax.naming.directory.Attribute attribute, AttributeType attributeType ) 147 throws LdapException 148 { 149 if ( attribute == null ) 150 { 151 return null; 152 } 153 154 try 155 { 156 Attribute serverAttribute = new DefaultAttribute( attributeType ); 157 158 for ( NamingEnumeration<?> values = attribute.getAll(); values.hasMoreElements(); ) 159 { 160 Object value = values.nextElement(); 161 int nbAdded = 0; 162 163 if ( value == null ) 164 { 165 continue; 166 } 167 168 if ( serverAttribute.isHumanReadable() ) 169 { 170 if ( value instanceof String ) 171 { 172 nbAdded = serverAttribute.add( ( String ) value ); 173 } 174 else if ( value instanceof byte[] ) 175 { 176 nbAdded = serverAttribute.add( Strings.utf8ToString( ( byte[] ) value ) ); 177 } 178 else 179 { 180 throw new LdapInvalidAttributeTypeException(); 181 } 182 } 183 else 184 { 185 if ( value instanceof String ) 186 { 187 nbAdded = serverAttribute.add( Strings.getBytesUtf8( ( String ) value ) ); 188 } 189 else if ( value instanceof byte[] ) 190 { 191 nbAdded = serverAttribute.add( ( byte[] ) value ); 192 } 193 else 194 { 195 throw new LdapInvalidAttributeTypeException(); 196 } 197 } 198 199 if ( nbAdded == 0 ) 200 { 201 throw new LdapInvalidAttributeTypeException(); 202 } 203 } 204 205 return serverAttribute; 206 } 207 catch ( NamingException ne ) 208 { 209 throw new LdapInvalidAttributeTypeException(); 210 } 211 } 212 213 214 /** 215 * Convert a BasicAttributes or a AttributesImpl to a ServerEntry 216 * 217 * @param attributes the BasicAttributes or AttributesImpl instance to convert 218 * @param dn The Dn which is needed by the ServerEntry 219 * @param schemaManager The SchemaManager instance 220 * @return An instance of a ServerEntry object 221 * 222 * @throws LdapInvalidAttributeTypeException If we get an invalid attribute 223 */ 224 public static Entry toServerEntry( Attributes attributes, Dn dn, SchemaManager schemaManager ) 225 throws LdapInvalidAttributeTypeException 226 { 227 if ( attributes instanceof BasicAttributes ) 228 { 229 try 230 { 231 Entry entry = new DefaultEntry( schemaManager, dn ); 232 233 for ( NamingEnumeration<? extends javax.naming.directory.Attribute> attrs = attributes.getAll(); attrs 234 .hasMoreElements(); ) 235 { 236 javax.naming.directory.Attribute attr = attrs.nextElement(); 237 238 String attributeId = attr.getID(); 239 String id = SchemaUtils.stripOptions( attributeId ); 240 Set<String> options = SchemaUtils.getOptions( attributeId ); 241 // TODO : handle options. 242 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 243 Attribute serverAttribute = ServerEntryUtils.toServerAttribute( attr, attributeType ); 244 245 if ( serverAttribute != null ) 246 { 247 entry.put( serverAttribute ); 248 } 249 } 250 251 return entry; 252 } 253 catch ( LdapException ne ) 254 { 255 throw new LdapInvalidAttributeTypeException( ne.getLocalizedMessage() ); 256 } 257 } 258 else 259 { 260 return null; 261 } 262 } 263 264 265 /** 266 * Gets the target entry as it would look after a modification operation 267 * was performed on it. 268 * 269 * @param mod the modification 270 * @param entry the source entry that is modified 271 * @param schemaManager The SchemaManager instance 272 * @return the resultant entry after the modification has taken place 273 * @throws LdapException if there are problems accessing attributes 274 */ 275 public static Entry getTargetEntry( Modification mod, Entry entry, SchemaManager schemaManager ) 276 throws LdapException 277 { 278 Entry targetEntry = entry.clone(); 279 ModificationOperation modOp = mod.getOperation(); 280 String id = mod.getAttribute().getUpId(); 281 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 282 283 switch ( modOp ) 284 { 285 case REPLACE_ATTRIBUTE: 286 targetEntry.put( mod.getAttribute() ); 287 break; 288 289 case REMOVE_ATTRIBUTE: 290 Attribute toBeRemoved = mod.getAttribute(); 291 292 if ( toBeRemoved.size() == 0 ) 293 { 294 targetEntry.removeAttributes( id ); 295 } 296 else 297 { 298 Attribute existing = targetEntry.get( id ); 299 300 if ( existing != null ) 301 { 302 for ( Value value : toBeRemoved ) 303 { 304 existing.remove( value ); 305 } 306 } 307 } 308 break; 309 310 case ADD_ATTRIBUTE: 311 Attribute combined = new DefaultAttribute( id, attributeType ); 312 Attribute toBeAdded = mod.getAttribute(); 313 Attribute existing = entry.get( id ); 314 315 if ( existing != null ) 316 { 317 for ( Value value : existing ) 318 { 319 combined.add( value ); 320 } 321 } 322 323 for ( Value value : toBeAdded ) 324 { 325 combined.add( value ); 326 } 327 328 targetEntry.put( combined ); 329 break; 330 331 default: 332 throw new IllegalStateException( I18n.err( I18n.ERR_464, modOp ) ); 333 } 334 335 return targetEntry; 336 } 337 338 339 /** 340 * Creates a new attribute which contains the values representing the union 341 * of two attributes. If one attribute is null then the resultant attribute 342 * returned is a copy of the non-null attribute. If both are null then we 343 * cannot determine the attribute ID and an {@link IllegalArgumentException} 344 * is raised. 345 * 346 * @param attr0 the first attribute 347 * @param attr1 the second attribute 348 * @return a new attribute with the union of values from both attribute 349 * arguments 350 * @throws LdapException if there are problems accessing attribute values 351 */ 352 public static Attribute getUnion( Attribute attr0, Attribute attr1 ) throws LdapException 353 { 354 if ( attr0 == null && attr1 == null ) 355 { 356 throw new IllegalArgumentException( I18n.err( I18n.ERR_465 ) ); 357 } 358 else if ( attr0 == null ) 359 { 360 return attr1.clone(); 361 } 362 else if ( attr1 == null ) 363 { 364 return attr0.clone(); 365 } 366 else if ( !attr0.getAttributeType().equals( attr1.getAttributeType() ) ) 367 { 368 throw new IllegalArgumentException( I18n.err( I18n.ERR_466 ) ); 369 } 370 371 Attribute attr = attr0.clone(); 372 373 for ( Value value : attr1 ) 374 { 375 attr.add( value ); 376 } 377 378 return attr; 379 } 380 381 382 /** 383 * Convert a ModificationItem to an instance of a ServerModification object 384 * 385 * @param modificationImpl the modification instance to convert 386 * @param attributeType the associated attributeType 387 * @return a instance of a ServerModification object 388 */ 389 private static Modification toServerModification( ModificationItem modificationImpl, AttributeType attributeType ) 390 throws LdapException 391 { 392 ModificationOperation operation; 393 394 switch ( modificationImpl.getModificationOp() ) 395 { 396 case DirContext.REMOVE_ATTRIBUTE: 397 operation = ModificationOperation.REMOVE_ATTRIBUTE; 398 break; 399 400 case DirContext.REPLACE_ATTRIBUTE: 401 operation = ModificationOperation.REPLACE_ATTRIBUTE; 402 break; 403 404 case DirContext.ADD_ATTRIBUTE: 405 default: 406 operation = ModificationOperation.ADD_ATTRIBUTE; 407 break; 408 409 } 410 411 return new DefaultModification( operation, 412 ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) ); 413 } 414 415 416 /** 417 * 418 * Convert a list of ModificationItemImpl to a list of LDAP API Modifications 419 * 420 * @param modificationItems The modificationItems to convert 421 * @param schemaManager The SchemaManager instance 422 * @return A list of converted Modification 423 * @throws LdapException If the conversion failed 424 */ 425 public static List<Modification> convertToServerModification( List<ModificationItem> modificationItems, 426 SchemaManager schemaManager ) throws LdapException 427 { 428 if ( modificationItems != null ) 429 { 430 List<Modification> modifications = new ArrayList<>( modificationItems.size() ); 431 432 for ( ModificationItem modificationItem : modificationItems ) 433 { 434 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( modificationItem 435 .getAttribute().getID() ); 436 modifications.add( toServerModification( modificationItem, attributeType ) ); 437 } 438 439 return modifications; 440 } 441 else 442 { 443 return null; 444 } 445 } 446 447 448 /** 449 * Convert a Modification to an instance of a ServerModification object. 450 * 451 * @param modificationImpl the modification instance to convert 452 * @param attributeType the associated attributeType 453 * @return a instance of a ServerModification object 454 */ 455 private static Modification toServerModification( Modification modification, AttributeType attributeType ) 456 throws LdapException 457 { 458 return new DefaultModification( 459 modification.getOperation(), 460 new DefaultAttribute( attributeType, modification.getAttribute() ) ); 461 } 462 463 464 /** 465 * Convert a JNDI set of Modifications to LDAP API Modifications 466 * 467 * @param modifications The modifications to convert 468 * @param schemaManager The SchemaManager instance 469 * @return The list of converted Modifications 470 * @throws LdapException If the conversion failed 471 */ 472 public static List<Modification> toServerModification( Modification[] modifications, 473 SchemaManager schemaManager ) throws LdapException 474 { 475 if ( modifications != null ) 476 { 477 List<Modification> modificationsList = new ArrayList<>(); 478 479 for ( Modification modification : modifications ) 480 { 481 String attributeId = modification.getAttribute().getUpId(); 482 String id = stripOptions( attributeId ); 483 modification.getAttribute().setUpId( id ); 484 Set<String> options = getOptions( attributeId ); 485 486 // ------------------------------------------------------------------- 487 // DIRSERVER-646 Fix: Replacing an unknown attribute with no values 488 // (deletion) causes an error 489 // ------------------------------------------------------------------- 490 if ( !schemaManager.getAttributeTypeRegistry().contains( id ) 491 && modification.getAttribute().size() == 0 492 && modification.getOperation() == ModificationOperation.REPLACE_ATTRIBUTE ) 493 { 494 // The attributeType does not exist in the schema. 495 // It's an error 496 String message = I18n.err( I18n.ERR_467, id ); 497 throw new LdapInvalidAttributeTypeException( message ); 498 } 499 else 500 { 501 // TODO : handle options 502 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 503 modificationsList.add( toServerModification( modification, attributeType ) ); 504 } 505 } 506 507 return modificationsList; 508 } 509 else 510 { 511 return null; 512 } 513 } 514 515 516 /** 517 * Convert a JNDI set of ModificationItems to LDAP API Modifications 518 * 519 * @param modifications The modificationItems to convert 520 * @param schemaManager The SchemaManager instance 521 * @return The list of converted ModificationItems 522 * @throws LdapException If the conversion failed 523 */ 524 public static List<Modification> toServerModification( ModificationItem[] modifications, 525 SchemaManager schemaManager ) throws LdapException 526 { 527 if ( modifications != null ) 528 { 529 List<Modification> modificationsList = new ArrayList<>(); 530 531 for ( ModificationItem modification : modifications ) 532 { 533 String attributeId = modification.getAttribute().getID(); 534 String id = stripOptions( attributeId ); 535 Set<String> options = getOptions( attributeId ); 536 537 // ------------------------------------------------------------------- 538 // DIRSERVER-646 Fix: Replacing an unknown attribute with no values 539 // (deletion) causes an error 540 // ------------------------------------------------------------------- 541 542 // TODO - after removing JNDI we need to make the server handle 543 // this in the codec 544 545 if ( !schemaManager.getAttributeTypeRegistry().contains( id ) 546 && modification.getAttribute().size() == 0 547 && modification.getModificationOp() == DirContext.REPLACE_ATTRIBUTE ) 548 { 549 continue; 550 } 551 552 // ------------------------------------------------------------------- 553 // END DIRSERVER-646 Fix 554 // ------------------------------------------------------------------- 555 556 // TODO : handle options 557 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 558 modificationsList.add( toServerModification( modification, attributeType ) ); 559 } 560 561 return modificationsList; 562 } 563 else 564 { 565 return null; 566 } 567 } 568 569 570 /** 571 * Utility method to extract a modification item from an array of modifications. 572 * 573 * @param mods the array of ModificationItems to extract the Attribute from. 574 * @param type the attributeType spec of the Attribute to extract 575 * @return the modification item on the attributeType specified 576 */ 577 public static Modification getModificationItem( List<Modification> mods, AttributeType type ) 578 { 579 for ( Modification modification : mods ) 580 { 581 Attribute attribute = modification.getAttribute(); 582 583 if ( attribute.getAttributeType() == type ) 584 { 585 return modification; 586 } 587 } 588 589 return null; 590 } 591 592 593 /** 594 * Utility method to extract an attribute from a list of modifications. 595 * 596 * @param mods the list of ModificationItems to extract the Attribute from. 597 * @param type the attributeType spec of the Attribute to extract 598 * @return the extract Attribute or null if no such attribute exists 599 */ 600 public static Attribute getAttribute( List<Modification> mods, AttributeType type ) 601 { 602 Modification mod = getModificationItem( mods, type ); 603 604 if ( mod != null ) 605 { 606 return mod.getAttribute(); 607 } 608 609 return null; 610 } 611 612 613 /** 614 * Encapsulate a ServerSearchResult enumeration into a SearchResult enumeration 615 * @param result The ServerSearchResult enumeration 616 * @return A SearchResultEnumeration 617 */ 618 public static NamingEnumeration<SearchResult> toSearchResultEnum( final NamingEnumeration<ServerSearchResult> result ) 619 { 620 if ( result instanceof EmptyEnumeration<?> ) 621 { 622 return new EmptyEnumeration<>(); 623 } 624 625 return new NamingEnumeration<SearchResult>() 626 { 627 public void close() throws NamingException 628 { 629 result.close(); 630 } 631 632 633 /** 634 * @see javax.naming.NamingEnumeration#hasMore() 635 */ 636 public boolean hasMore() throws NamingException 637 { 638 return result.hasMore(); 639 } 640 641 642 /** 643 * @see javax.naming.NamingEnumeration#next() 644 */ 645 public SearchResult next() throws NamingException 646 { 647 ServerSearchResult rec = result.next(); 648 649 return new SearchResult( 650 rec.getDn().getName(), 651 rec.getObject(), 652 toBasicAttributes( rec.getServerEntry() ), 653 rec.isRelative() ); 654 } 655 656 657 /** 658 * @see java.util.Enumeration#hasMoreElements() 659 */ 660 public boolean hasMoreElements() 661 { 662 return result.hasMoreElements(); 663 } 664 665 666 /** 667 * @see java.util.Enumeration#nextElement() 668 */ 669 public SearchResult nextElement() 670 { 671 try 672 { 673 ServerSearchResult rec = result.next(); 674 675 return new SearchResult( 676 rec.getDn().getName(), 677 rec.getObject(), 678 toBasicAttributes( rec.getServerEntry() ), 679 rec.isRelative() ); 680 } 681 catch ( NamingException ne ) 682 { 683 NoSuchElementException nsee = 684 new NoSuchElementException( I18n.err( I18n.ERR_468 ) ); 685 nsee.initCause( ne ); 686 throw nsee; 687 } 688 } 689 }; 690 } 691 692 693 /** 694 * Remove the options from the attributeType, and returns the ID. 695 * 696 * RFC 4512 : 697 * attributedescription = attributetype options 698 * attributetype = oid 699 * options = *( SEMI option ) 700 * option = 1*keychar 701 */ 702 private static String stripOptions( String attributeId ) 703 { 704 int optionsPos = attributeId.indexOf( ';' ); 705 706 if ( optionsPos != -1 ) 707 { 708 return attributeId.substring( 0, optionsPos ); 709 } 710 else 711 { 712 return attributeId; 713 } 714 } 715 716 717 /** 718 * Get the options from the attributeType. 719 * 720 * For instance, given : 721 * jpegphoto;binary;lang=jp 722 * 723 * your get back a set containing { "binary", "lang=jp" } 724 */ 725 private static Set<String> getOptions( String attributeId ) 726 { 727 int optionsPos = attributeId.indexOf( ';' ); 728 729 if ( optionsPos != -1 ) 730 { 731 Set<String> options = new HashSet<>(); 732 733 String[] res = attributeId.substring( optionsPos + 1 ).split( ";" ); 734 735 for ( String option : res ) 736 { 737 if ( !Strings.isEmpty( option ) ) 738 { 739 options.add( option ); 740 } 741 } 742 743 return options; 744 } 745 else 746 { 747 return null; 748 } 749 } 750 751 752 /** 753 * Filters an entry accordingly to the requested Attribute list. 754 * 755 * @param schemaManager The SchemaManager instance 756 * @param operationContext The SearchingOperationContext 757 * @param entry The entry to filter 758 * @throws LdapException If the filtering fails 759 */ 760 public static void filterContents( SchemaManager schemaManager, FilteringOperationContext operationContext, 761 Entry entry ) throws LdapException 762 { 763 boolean typesOnly = operationContext.isTypesOnly(); 764 765 boolean returnAll = ( operationContext.isAllOperationalAttributes() && operationContext.isAllUserAttributes() ) 766 && ( !typesOnly ); 767 768 if ( returnAll ) 769 { 770 return; 771 } 772 773 // for special handling of entryDN attribute, see DIRSERVER-1902 774 Entry originalEntry = ( ( ClonedServerEntry ) entry ).getOriginalEntry(); 775 776 AttributeType entryDnType = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.ENTRY_DN_AT_OID ); 777 AttributeType refType = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.REF_AT_OID ); 778 779 // First, remove all the attributes if we have the NoAttribute flag set to true 780 if ( operationContext.isNoAttributes() ) 781 { 782 for ( Attribute attribute : originalEntry ) 783 { 784 AttributeType attributeType = attribute.getAttributeType(); 785 786 // Bypass the ref attribute, unless the ManageDSAIT control is present 787 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) ) 788 { 789 continue; 790 } 791 792 entry.remove( entry.get( attributeType ) ); 793 } 794 795 entry.removeAttributes( entryDnType ); 796 797 return; 798 } 799 800 // If the user has requested all the User attributes ('*') only, we filter the entry's attribute to keep only 801 // the USER attributes, plus the Operational attributes in the returning list 802 if ( operationContext.isAllUserAttributes() ) 803 { 804 for ( Attribute attribute : originalEntry ) 805 { 806 AttributeType attributeType = attribute.getAttributeType(); 807 808 // Bypass the ref attribute, unless the ManageDSAIT control is present 809 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) ) 810 { 811 continue; 812 } 813 814 if ( attributeType.isOperational() ) 815 { 816 if ( !operationContext.contains( schemaManager, attributeType ) ) 817 { 818 entry.removeAttributes( attributeType ); 819 } 820 else if ( typesOnly ) 821 { 822 entry.get( attributeType ).clear(); 823 } 824 } 825 else if ( typesOnly ) 826 { 827 entry.get( attributeType ).clear(); 828 } 829 } 830 831 // DIRSERVER-1953 832 if ( !operationContext.contains( schemaManager, entryDnType ) ) 833 { 834 entry.removeAttributes( entryDnType ); 835 } 836 837 return; 838 } 839 840 // If the user has requested all the Operational attributes ('+') only, we filter the entry's attribute to keep only 841 // the OPERATIONAL attributes, plus the User attributes in the returning list 842 if ( operationContext.isAllOperationalAttributes() ) 843 { 844 for ( Attribute attribute : originalEntry ) 845 { 846 AttributeType attributeType = attribute.getAttributeType(); 847 848 if ( attributeType.isUser() ) 849 { 850 if ( !operationContext.contains( schemaManager, attributeType ) ) 851 { 852 entry.removeAttributes( attributeType ); 853 } 854 else if ( typesOnly ) 855 { 856 entry.get( attributeType ).clear(); 857 } 858 } 859 else if ( typesOnly ) 860 { 861 entry.get( attributeType ).clear(); 862 } 863 } 864 865 if ( !operationContext.contains( schemaManager, entryDnType ) ) 866 { 867 entry.removeAttributes( entryDnType ); 868 } 869 else if ( typesOnly ) 870 { 871 entry.get( entryDnType ).clear(); 872 } 873 874 return; 875 } 876 877 // Last, not least, check if the attributes are in the returning list 878 if ( operationContext.getReturningAttributes() != null ) 879 { 880 for ( Attribute attribute : originalEntry ) 881 { 882 AttributeType attributeType = attribute.getAttributeType(); 883 884 // Bypass the ref attribute, unless the ManageDSAIT control is present 885 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) ) 886 { 887 continue; 888 } 889 890 if ( !operationContext.contains( schemaManager, attributeType ) ) 891 { 892 entry.removeAttributes( attributeType ); 893 continue; 894 } 895 896 boolean isNotRequested = true; 897 898 for ( AttributeTypeOptions attrOptions : operationContext.getReturningAttributes() ) 899 { 900 if ( attrOptions.getAttributeType().equals( attributeType ) 901 || attrOptions.getAttributeType().isAncestorOf( attributeType ) ) 902 { 903 isNotRequested = false; 904 break; 905 } 906 } 907 908 if ( isNotRequested ) 909 { 910 entry.removeAttributes( attributeType ); 911 } 912 else if ( typesOnly ) 913 { 914 entry.get( attributeType ).clear(); 915 } 916 } 917 918 if ( !operationContext.contains( schemaManager, entryDnType ) ) 919 { 920 entry.removeAttributes( entryDnType ); 921 } 922 else if ( typesOnly ) 923 { 924 entry.get( entryDnType ).clear(); 925 } 926 } 927 } 928}