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.api.ldap.model.entry; 020 021 022import java.io.IOException; 023import java.io.ObjectInput; 024import java.io.ObjectOutput; 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.Collections; 028import java.util.HashMap; 029import java.util.Iterator; 030import java.util.List; 031import java.util.Map; 032 033import org.apache.directory.api.i18n.I18n; 034import org.apache.directory.api.ldap.model.constants.SchemaConstants; 035import org.apache.directory.api.ldap.model.exception.LdapException; 036import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; 037import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 038import org.apache.directory.api.ldap.model.ldif.LdapLdifException; 039import org.apache.directory.api.ldap.model.ldif.LdifAttributesReader; 040import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 041import org.apache.directory.api.ldap.model.name.Dn; 042import org.apache.directory.api.ldap.model.schema.AttributeType; 043import org.apache.directory.api.ldap.model.schema.SchemaManager; 044import org.apache.directory.api.util.Base64; 045import org.apache.directory.api.util.Strings; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049 050/** 051 * A default implementation of a ServerEntry which should suite most 052 * use cases.<br/> 053 * <br/> 054 * This class is final, it should not be extended. 055 * 056 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 057 */ 058public final class DefaultEntry implements Entry 059{ 060 /** Used for serialization */ 061 private static final long serialVersionUID = 2L; 062 063 /** The logger for this class */ 064 private static final Logger LOG = LoggerFactory.getLogger( DefaultEntry.class ); 065 066 /** The Dn for this entry */ 067 private Dn dn; 068 069 /** A map containing all the attributes for this entry */ 070 private Map<String, Attribute> attributes = new HashMap<String, Attribute>(); 071 072 /** A speedup to get the ObjectClass attribute */ 073 private static AttributeType objectClassAttributeType; 074 075 /** The SchemaManager */ 076 private SchemaManager schemaManager; 077 078 /** The computed hashcode. We don't want to compute it each time the hashcode() method is called */ 079 private volatile int h; 080 081 /** A mutex to manage synchronization*/ 082 private static final Object MUTEX = new Object(); 083 084 085 //------------------------------------------------------------------------- 086 // Constructors 087 //------------------------------------------------------------------------- 088 /** 089 * Creates a new instance of DefaultEntry. 090 * <p> 091 * This entry <b>must</b> be initialized before being used ! 092 */ 093 public DefaultEntry() 094 { 095 this( ( SchemaManager ) null ); 096 } 097 098 099 /** 100 * <p> 101 * Creates a new instance of DefaultEntry, schema aware. 102 * </p> 103 * <p> 104 * No attributes will be created. 105 * </p> 106 * 107 * @param schemaManager The reference to the schemaManager 108 */ 109 public DefaultEntry( SchemaManager schemaManager ) 110 { 111 this.schemaManager = schemaManager; 112 dn = Dn.EMPTY_DN; 113 114 // Initialize the ObjectClass object 115 if ( schemaManager != null ) 116 { 117 initObjectClassAT(); 118 } 119 } 120 121 122 /** 123 * Creates a new instance of DefaultEntry, with a Dn. 124 * 125 * @param dn The String Dn for this serverEntry. Can be null. 126 * @throws LdapInvalidDnException If the Dn is invalid 127 */ 128 public DefaultEntry( String dn ) throws LdapInvalidDnException 129 { 130 this.dn = new Dn( dn ); 131 } 132 133 134 /** 135 * Creates a new instance of DefaultEntry, with a Dn. 136 * 137 * @param dn The Dn for this serverEntry. Can be null. 138 */ 139 public DefaultEntry( Dn dn ) 140 { 141 this.dn = dn; 142 } 143 144 145 /** 146 * <p> 147 * Creates a new instance of DefaultEntry, schema aware. 148 * </p> 149 * <p> 150 * No attributes will be created. 151 * </p> 152 * 153 * @param schemaManager The reference to the schemaManager 154 * @param dn The String Dn for this serverEntry. Can be null. 155 * @throws LdapInvalidDnException If the Dn is invalid 156 */ 157 public DefaultEntry( SchemaManager schemaManager, String dn ) throws LdapInvalidDnException 158 { 159 this.schemaManager = schemaManager; 160 161 if ( Strings.isEmpty( dn ) ) 162 { 163 this.dn = Dn.EMPTY_DN; 164 } 165 else 166 { 167 this.dn = new Dn( dn ); 168 normalizeDN( this.dn ); 169 } 170 171 // Initialize the ObjectClass object 172 initObjectClassAT(); 173 } 174 175 176 /** 177 * <p> 178 * Creates a new instance of DefaultEntry, schema aware. 179 * </p> 180 * <p> 181 * No attributes will be created. 182 * </p> 183 * 184 * @param schemaManager The reference to the schemaManager 185 * @param dn The Dn for this serverEntry. Can be null. 186 */ 187 public DefaultEntry( SchemaManager schemaManager, Dn dn ) 188 { 189 this.schemaManager = schemaManager; 190 191 if ( dn == null ) 192 { 193 this.dn = Dn.EMPTY_DN; 194 } 195 else 196 { 197 this.dn = dn; 198 normalizeDN( this.dn ); 199 } 200 201 // Initialize the ObjectClass object 202 initObjectClassAT(); 203 } 204 205 206 /** 207 * Creates a new instance of DefaultEntry, with a 208 * Dn and a list of IDs. 209 * 210 * @param dn The Dn for this serverEntry. Can be null. 211 * @param upIds The list of attributes to create. 212 */ 213 public DefaultEntry( String dn, Object... elements ) throws LdapException 214 { 215 this( null, dn, elements ); 216 } 217 218 219 /** 220 * Creates a new instance of DefaultEntry, with a 221 * Dn and a list of IDs. 222 * 223 * @param dn The Dn for this serverEntry. Can be null. 224 * @param upIds The list of attributes to create. 225 */ 226 public DefaultEntry( Dn dn, Object... elements ) throws LdapException 227 { 228 this( null, dn, elements ); 229 } 230 231 232 /** 233 * Creates a new instance of DefaultEntry, with a 234 * Dn and a list of IDs. 235 * 236 * @param dn The Dn for this serverEntry. Can be null. 237 * @param upIds The list of attributes to create. 238 */ 239 public DefaultEntry( SchemaManager schemaManager, String dn, Object... elements ) throws LdapException 240 { 241 this( schemaManager, new Dn( schemaManager, dn ), elements ); 242 } 243 244 245 /** 246 * Creates a new instance of DefaultEntry, with a 247 * Dn and a list of IDs. 248 * 249 * @param dn The Dn for this serverEntry. Can be null. 250 * @param upIds The list of attributes to create. 251 */ 252 public DefaultEntry( SchemaManager schemaManager, Dn dn, Object... elements ) throws LdapException 253 { 254 DefaultEntry entry = ( DefaultEntry ) createEntry( schemaManager, elements ); 255 256 this.dn = dn; 257 this.attributes = entry.attributes; 258 this.schemaManager = schemaManager; 259 260 if ( schemaManager != null ) 261 { 262 this.dn.apply( schemaManager ); 263 initObjectClassAT(); 264 } 265 } 266 267 268 /** 269 * <p> 270 * Creates a new instance of DefaultEntry, copying 271 * another entry. 272 * </p> 273 * <p> 274 * No attributes will be created. 275 * </p> 276 * 277 * @param schemaManager The reference to the schemaManager 278 * @param entry the entry to copy 279 */ 280 public DefaultEntry( SchemaManager schemaManager, Entry entry ) throws LdapException 281 { 282 this.schemaManager = schemaManager; 283 284 // Initialize the ObjectClass object 285 initObjectClassAT(); 286 287 // We will clone the existing entry, because it may be normalized 288 if ( entry.getDn() != null ) 289 { 290 dn = entry.getDn(); 291 normalizeDN( dn ); 292 } 293 else 294 { 295 dn = Dn.EMPTY_DN; 296 } 297 298 // Init the attributes map 299 attributes = new HashMap<String, Attribute>( entry.size() ); 300 301 // and copy all the attributes 302 for ( Attribute attribute : entry ) 303 { 304 try 305 { 306 // First get the AttributeType 307 AttributeType attributeType = attribute.getAttributeType(); 308 309 if ( attributeType == null ) 310 { 311 attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 312 } 313 314 // Create a new ServerAttribute. 315 Attribute serverAttribute = new DefaultAttribute( attributeType, attribute ); 316 317 // And store it 318 add( serverAttribute ); 319 } 320 catch ( LdapException ne ) 321 { 322 // Just log a warning 323 LOG.warn( "The attribute '" + attribute.getId() + "' cannot be stored" ); 324 throw ne; 325 } 326 } 327 } 328 329 330 //------------------------------------------------------------------------- 331 // Helper methods 332 //------------------------------------------------------------------------- 333 private Entry createEntry( SchemaManager schemaManager, Object... elements ) 334 throws LdapInvalidAttributeValueException, LdapLdifException 335 { 336 StringBuilder sb = new StringBuilder(); 337 int pos = 0; 338 boolean valueExpected = false; 339 340 for ( Object element : elements ) 341 { 342 if ( !valueExpected ) 343 { 344 if ( !( element instanceof String ) ) 345 { 346 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( 347 I18n.ERR_12085, ( pos + 1 ) ) ); 348 } 349 350 String attribute = ( String ) element; 351 sb.append( attribute ); 352 353 if ( attribute.indexOf( ':' ) != -1 ) 354 { 355 sb.append( '\n' ); 356 } 357 else 358 { 359 valueExpected = true; 360 } 361 } 362 else 363 { 364 if ( element instanceof String ) 365 { 366 sb.append( ": " ).append( ( String ) element ).append( '\n' ); 367 } 368 else if ( element instanceof byte[] ) 369 { 370 sb.append( ":: " ); 371 sb.append( new String( Base64.encode( ( byte[] ) element ) ) ); 372 sb.append( '\n' ); 373 } 374 else 375 { 376 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( 377 I18n.ERR_12086, ( pos + 1 ) ) ); 378 } 379 380 valueExpected = false; 381 } 382 } 383 384 if ( valueExpected ) 385 { 386 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n 387 .err( I18n.ERR_12087 ) ); 388 } 389 390 LdifAttributesReader reader = null; 391 392 try 393 { 394 reader = new LdifAttributesReader(); 395 Entry entry = reader.parseEntry( schemaManager, sb.toString() ); 396 397 return entry; 398 } 399 finally 400 { 401 try 402 { 403 reader.close(); 404 } 405 catch ( IOException e ) 406 { 407 e.printStackTrace(); 408 } 409 } 410 } 411 412 413 /** 414 * Get the trimmed and lower cased entry ID 415 */ 416 private String getId( String upId ) 417 { 418 String id = Strings.trim( Strings.toLowerCase( upId ) ); 419 420 // If empty, throw an error 421 if ( Strings.isEmpty( id ) ) 422 { 423 String message = I18n.err( I18n.ERR_04133 ); 424 LOG.error( message ); 425 throw new IllegalArgumentException( message ); 426 } 427 428 return id; 429 } 430 431 432 /** 433 * Get the UpId if it is null. 434 * 435 * @param upId The ID 436 */ 437 private String getUpId( String upId, AttributeType attributeType ) 438 { 439 String normUpId = Strings.trim( upId ); 440 441 if ( ( attributeType == null ) ) 442 { 443 if ( Strings.isEmpty( normUpId ) ) 444 { 445 String message = I18n.err( I18n.ERR_04458 ); 446 LOG.error( message ); 447 throw new IllegalArgumentException( message ); 448 } 449 450 return upId; 451 } 452 else if ( Strings.isEmpty( normUpId ) ) 453 { 454 String id = attributeType.getName(); 455 456 if ( Strings.isEmpty( id ) ) 457 { 458 id = attributeType.getOid(); 459 } 460 461 return id; 462 } 463 else 464 { 465 return upId; 466 } 467 } 468 469 470 /** 471 * This method is used to initialize the OBJECT_CLASS_AT attributeType. 472 * 473 * We want to do it only once, so it's a synchronized method. Note that 474 * the alternative would be to call the lookup() every time, but this won't 475 * be very efficient, as it will get the AT from a map, which is also 476 * synchronized, so here, we have a very minimal cost. 477 * 478 * We can't do it once as a static part in the body of this class, because 479 * the access to the registries is mandatory to get back the AttributeType. 480 */ 481 private void initObjectClassAT() 482 { 483 if ( schemaManager == null ) 484 { 485 return; 486 } 487 488 try 489 { 490 synchronized ( MUTEX ) 491 { 492 if ( objectClassAttributeType == null ) 493 { 494 objectClassAttributeType = schemaManager 495 .lookupAttributeTypeRegistry( SchemaConstants.OBJECT_CLASS_AT ); 496 } 497 } 498 } 499 catch ( LdapException ne ) 500 { 501 // do nothing... 502 } 503 } 504 505 506 /** 507 * normalizes the given Dn if it was not already normalized 508 * 509 * @param dn the Dn to be normalized 510 */ 511 private void normalizeDN( Dn dn ) 512 { 513 if ( !dn.isSchemaAware() ) 514 { 515 try 516 { 517 // The dn must be normalized 518 dn.apply( schemaManager ); 519 } 520 catch ( LdapException ne ) 521 { 522 LOG.warn( "The Dn '{}' cannot be normalized", dn ); 523 } 524 } 525 } 526 527 528 /** 529 * A helper method to recompute the hash code 530 */ 531 private void rehash() 532 { 533 h = 37; 534 h = h * 17 + dn.hashCode(); 535 } 536 537 538 /** 539 * Add a new EntryAttribute, with its upId. If the upId is null, 540 * default to the AttributeType name. 541 * 542 * Updates the AttributeMap. 543 */ 544 protected void createAttribute( String upId, AttributeType attributeType, byte[]... values ) 545 throws LdapInvalidAttributeValueException 546 { 547 Attribute attribute = new DefaultAttribute( attributeType, values ); 548 attribute.setUpId( upId, attributeType ); 549 attributes.put( attributeType.getOid(), attribute ); 550 } 551 552 553 /** 554 * Add a new EntryAttribute, with its upId. If the upId is null, 555 * default to the AttributeType name. 556 * 557 * Updates the AttributeMap. 558 */ 559 protected void createAttribute( String upId, AttributeType attributeType, String... values ) 560 throws LdapInvalidAttributeValueException 561 { 562 Attribute attribute = new DefaultAttribute( attributeType, values ); 563 attribute.setUpId( upId, attributeType ); 564 attributes.put( attributeType.getOid(), attribute ); 565 } 566 567 568 /** 569 * Add a new EntryAttribute, with its upId. If the upId is null, 570 * default to the AttributeType name. 571 * 572 * Updates the AttributeMap. 573 */ 574 protected void createAttribute( String upId, AttributeType attributeType, Value<?>... values ) 575 throws LdapInvalidAttributeValueException 576 { 577 Attribute attribute = new DefaultAttribute( attributeType, values ); 578 attribute.setUpId( upId, attributeType ); 579 attributes.put( attributeType.getOid(), attribute ); 580 } 581 582 583 /** 584 * Returns the attributeType from an Attribute ID. 585 */ 586 protected AttributeType getAttributeType( String upId ) throws LdapException 587 { 588 if ( Strings.isEmpty( Strings.trim( upId ) ) ) 589 { 590 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 591 LOG.error( message ); 592 throw new IllegalArgumentException( message ); 593 } 594 595 return schemaManager.lookupAttributeTypeRegistry( upId ); 596 } 597 598 599 //------------------------------------------------------------------------- 600 // Entry methods 601 //------------------------------------------------------------------------- 602 /** 603 * {@inheritDoc} 604 */ 605 public Entry add( AttributeType attributeType, byte[]... values ) throws LdapException 606 { 607 if ( attributeType == null ) 608 { 609 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 610 LOG.error( message ); 611 throw new IllegalArgumentException( message ); 612 } 613 614 if ( ( values == null ) || ( values.length == 0 ) ) 615 { 616 String message = I18n.err( I18n.ERR_04478_NO_VALUE_NOT_ALLOWED ); 617 LOG.error( message ); 618 throw new IllegalArgumentException( message ); 619 } 620 621 // ObjectClass with binary values are not allowed 622 if ( attributeType.equals( objectClassAttributeType ) ) 623 { 624 String message = I18n.err( I18n.ERR_04461 ); 625 LOG.error( message ); 626 throw new UnsupportedOperationException( message ); 627 } 628 629 Attribute attribute = attributes.get( attributeType.getOid() ); 630 631 if ( attribute != null ) 632 { 633 // This Attribute already exist, we add the values 634 // into it 635 attribute.add( values ); 636 } 637 else 638 { 639 // We have to create a new Attribute and set the values. 640 // The upId, which is set to null, will be setup by the 641 // createAttribute method 642 createAttribute( null, attributeType, values ); 643 } 644 645 return this; 646 } 647 648 649 /** 650 * {@inheritDoc} 651 */ 652 public Entry add( AttributeType attributeType, String... values ) throws LdapException 653 { 654 if ( attributeType == null ) 655 { 656 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 657 LOG.error( message ); 658 throw new IllegalArgumentException( message ); 659 } 660 661 Attribute attribute = attributes.get( attributeType.getOid() ); 662 663 if ( attribute != null ) 664 { 665 // This Attribute already exist, we add the values 666 // into it 667 attribute.add( values ); 668 } 669 else 670 { 671 // We have to create a new Attribute and set the values. 672 // The upId, which is set to null, will be setup by the 673 // createAttribute method 674 createAttribute( null, attributeType, values ); 675 } 676 677 return this; 678 } 679 680 681 /** 682 * {@inheritDoc} 683 */ 684 public Entry add( AttributeType attributeType, Value<?>... values ) throws LdapException 685 { 686 if ( attributeType == null ) 687 { 688 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 689 LOG.error( message ); 690 throw new IllegalArgumentException( message ); 691 } 692 693 Attribute attribute = attributes.get( attributeType.getOid() ); 694 695 if ( attribute != null ) 696 { 697 // This Attribute already exist, we add the values 698 // into it 699 attribute.add( values ); 700 } 701 else 702 { 703 // We have to create a new Attribute and set the values. 704 // The upId, which is set to null, will be setup by the 705 // createAttribute method 706 createAttribute( null, attributeType, values ); 707 } 708 709 return this; 710 } 711 712 713 /** 714 * {@inheritDoc} 715 */ 716 public Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException 717 { 718 // ObjectClass with binary values are not allowed 719 if ( attributeType.equals( objectClassAttributeType ) ) 720 { 721 String message = I18n.err( I18n.ERR_04461 ); 722 LOG.error( message ); 723 throw new UnsupportedOperationException( message ); 724 } 725 726 Attribute attribute = attributes.get( attributeType.getOid() ); 727 728 String id = getUpId( upId, attributeType ); 729 730 if ( attribute != null ) 731 { 732 // This Attribute already exist, we add the values 733 // into it 734 attribute.add( values ); 735 attribute.setUpId( id, attributeType ); 736 } 737 else 738 { 739 // We have to create a new Attribute and set the values 740 // and the upId 741 createAttribute( id, attributeType, values ); 742 } 743 744 return this; 745 } 746 747 748 /** 749 * {@inheritDoc} 750 */ 751 public Entry add( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException 752 { 753 if ( attributeType == null ) 754 { 755 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 756 LOG.error( message ); 757 throw new IllegalArgumentException( message ); 758 } 759 760 String id = getUpId( upId, attributeType ); 761 762 Attribute attribute = attributes.get( attributeType.getOid() ); 763 764 if ( attribute != null ) 765 { 766 // This Attribute already exist, we add the values 767 // into it 768 attribute.add( values ); 769 attribute.setUpId( id, attributeType ); 770 } 771 else 772 { 773 createAttribute( id, attributeType, values ); 774 } 775 776 return this; 777 } 778 779 780 /** 781 * {@inheritDoc} 782 */ 783 public Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException 784 { 785 if ( attributeType == null ) 786 { 787 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 788 LOG.error( message ); 789 throw new IllegalArgumentException( message ); 790 } 791 792 String id = getUpId( upId, attributeType ); 793 794 Attribute attribute = attributes.get( attributeType.getOid() ); 795 796 if ( attribute != null ) 797 { 798 // This Attribute already exist, we add the values 799 // into it 800 attribute.add( values ); 801 attribute.setUpId( id, attributeType ); 802 } 803 else 804 { 805 // We have to create a new Attribute and set the values 806 // and the upId 807 createAttribute( id, attributeType, values ); 808 } 809 810 return this; 811 } 812 813 814 /** 815 * {@inheritDoc} 816 */ 817 public Entry add( Attribute... attributes ) throws LdapException 818 { 819 // Loop on all the added attributes 820 for ( Attribute attribute : attributes ) 821 { 822 AttributeType attributeType = attribute.getAttributeType(); 823 824 if ( attributeType != null ) 825 { 826 String oid = attributeType.getOid(); 827 828 if ( this.attributes.containsKey( oid ) ) 829 { 830 // We already have an attribute with the same AttributeType 831 // Just add the new values into it. 832 Attribute existingAttribute = this.attributes.get( oid ); 833 834 for ( Value<?> value : attribute ) 835 { 836 existingAttribute.add( value ); 837 } 838 839 // And update the upId 840 existingAttribute.setUpId( attribute.getUpId() ); 841 } 842 else 843 { 844 // The attributeType does not exist, add it 845 this.attributes.put( oid, attribute ); 846 } 847 } 848 else 849 { 850 // If the attribute already exist, we will add the new values. 851 if ( contains( attribute ) ) 852 { 853 Attribute existingAttribute = get( attribute.getId() ); 854 855 // Loop on all the values, and add them to the existing attribute 856 for ( Value<?> value : attribute ) 857 { 858 existingAttribute.add( value ); 859 } 860 } 861 else 862 { 863 // Stores the attribute into the entry 864 this.attributes.put( attribute.getId(), attribute ); 865 } 866 } 867 } 868 869 return this; 870 } 871 872 873 /** 874 * {@inheritDoc} 875 */ 876 public Entry add( String upId, byte[]... values ) throws LdapException 877 { 878 if ( Strings.isEmpty( upId ) ) 879 { 880 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 881 LOG.error( message ); 882 throw new IllegalArgumentException( message ); 883 } 884 885 // First, transform the upID to a valid ID 886 String id = getId( upId ); 887 888 if ( schemaManager != null ) 889 { 890 add( upId, schemaManager.lookupAttributeTypeRegistry( id ), values ); 891 } 892 else 893 { 894 // Now, check to see if we already have such an attribute 895 Attribute attribute = attributes.get( id ); 896 897 if ( attribute != null ) 898 { 899 // This Attribute already exist, we add the values 900 // into it. (If the values already exists, they will 901 // not be added, but this is done in the add() method) 902 attribute.add( values ); 903 attribute.setUpId( upId ); 904 } 905 else 906 { 907 // We have to create a new Attribute and set the values 908 // and the upId 909 attributes.put( id, new DefaultAttribute( upId, values ) ); 910 } 911 } 912 913 return this; 914 } 915 916 917 /** 918 * {@inheritDoc} 919 */ 920 public Entry add( String upId, String... values ) throws LdapException 921 { 922 if ( Strings.isEmpty( upId ) ) 923 { 924 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 925 LOG.error( message ); 926 throw new IllegalArgumentException( message ); 927 } 928 929 // First, transform the upID to a valid ID 930 String id = getId( upId ); 931 932 if ( schemaManager != null ) 933 { 934 add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values ); 935 } 936 else 937 { 938 // Now, check to see if we already have such an attribute 939 Attribute attribute = attributes.get( id ); 940 941 if ( attribute != null ) 942 { 943 // This Attribute already exist, we add the values 944 // into it. (If the values already exists, they will 945 // not be added, but this is done in the add() method) 946 attribute.add( values ); 947 attribute.setUpId( upId ); 948 } 949 else 950 { 951 // We have to create a new Attribute and set the values 952 // and the upId 953 attributes.put( id, new DefaultAttribute( upId, values ) ); 954 } 955 } 956 957 return this; 958 } 959 960 961 /** 962 * {@inheritDoc} 963 */ 964 public Entry add( String upId, Value<?>... values ) throws LdapException 965 { 966 if ( Strings.isEmpty( upId ) ) 967 { 968 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 969 LOG.error( message ); 970 throw new IllegalArgumentException( message ); 971 } 972 973 // First, transform the upID to a valid ID 974 String id = getId( upId ); 975 976 if ( schemaManager != null ) 977 { 978 add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values ); 979 } 980 else 981 { 982 // Now, check to see if we already have such an attribute 983 Attribute attribute = attributes.get( id ); 984 985 if ( attribute != null ) 986 { 987 // This Attribute already exist, we add the values 988 // into it. (If the values already exists, they will 989 // not be added, but this is done in the add() method) 990 attribute.add( values ); 991 attribute.setUpId( upId ); 992 } 993 else 994 { 995 // We have to create a new Attribute and set the values 996 // and the upId 997 attributes.put( id, new DefaultAttribute( upId, values ) ); 998 } 999 } 1000 1001 return this; 1002 } 1003 1004 1005 /** 1006 * Clone an entry. All the element are duplicated, so a modification on 1007 * the original object won't affect the cloned object, as a modification 1008 * on the cloned object has no impact on the original object 1009 */ 1010 public Entry clone() 1011 { 1012 // First, clone the structure 1013 DefaultEntry clone = ( DefaultEntry ) shallowClone(); 1014 1015 // now clone all the attributes 1016 clone.attributes.clear(); 1017 1018 if ( schemaManager != null ) 1019 { 1020 for ( Attribute attribute : attributes.values() ) 1021 { 1022 String oid = attribute.getAttributeType().getOid(); 1023 clone.attributes.put( oid, attribute.clone() ); 1024 } 1025 } 1026 else 1027 { 1028 for ( Attribute attribute : attributes.values() ) 1029 { 1030 clone.attributes.put( attribute.getId(), attribute.clone() ); 1031 } 1032 1033 } 1034 1035 // We are done ! 1036 return clone; 1037 } 1038 1039 1040 /** 1041 * Shallow clone an entry. We don't clone the Attributes 1042 */ 1043 @SuppressWarnings("unchecked") 1044 public Entry shallowClone() 1045 { 1046 try 1047 { 1048 // First, clone the structure 1049 DefaultEntry clone = ( DefaultEntry ) super.clone(); 1050 1051 // Just in case ... Should *never* happen 1052 if ( clone == null ) 1053 { 1054 return null; 1055 } 1056 1057 // An Entry has a Dn and many attributes. 1058 clone.dn = dn; // note that Dn is immutable now 1059 1060 // then clone the ClientAttribute Map. 1061 clone.attributes = ( Map<String, Attribute> ) ( ( ( HashMap<String, Attribute> ) attributes ) 1062 .clone() ); 1063 1064 // We are done ! 1065 return clone; 1066 } 1067 catch ( CloneNotSupportedException cnse ) 1068 { 1069 return null; 1070 } 1071 } 1072 1073 1074 /** 1075 * {@inheritDoc} 1076 */ 1077 public boolean contains( Attribute... attributes ) 1078 { 1079 if ( schemaManager == null ) 1080 { 1081 for ( Attribute attribute : attributes ) 1082 { 1083 if ( attribute == null ) 1084 { 1085 return this.attributes.size() == 0; 1086 } 1087 1088 if ( !this.attributes.containsKey( attribute.getId() ) ) 1089 { 1090 return false; 1091 } 1092 } 1093 } 1094 else 1095 { 1096 for ( Attribute entryAttribute : attributes ) 1097 { 1098 if ( entryAttribute == null ) 1099 { 1100 return this.attributes.size() == 0; 1101 } 1102 1103 AttributeType attributeType = entryAttribute.getAttributeType(); 1104 1105 if ( ( attributeType == null ) || !this.attributes.containsKey( attributeType.getOid() ) ) 1106 { 1107 return false; 1108 } 1109 } 1110 } 1111 1112 return true; 1113 } 1114 1115 1116 /** 1117 * {@inheritDoc} 1118 */ 1119 public boolean containsAttribute( String... attributes ) 1120 { 1121 if ( schemaManager == null ) 1122 { 1123 for ( String attribute : attributes ) 1124 { 1125 String id = getId( attribute ); 1126 1127 if ( !this.attributes.containsKey( id ) ) 1128 { 1129 return false; 1130 } 1131 } 1132 1133 return true; 1134 } 1135 else 1136 { 1137 for ( String attribute : attributes ) 1138 { 1139 try 1140 { 1141 if ( !containsAttribute( schemaManager.lookupAttributeTypeRegistry( attribute ) ) ) 1142 { 1143 return false; 1144 } 1145 } 1146 catch ( LdapException ne ) 1147 { 1148 return false; 1149 } 1150 } 1151 1152 return true; 1153 } 1154 } 1155 1156 1157 /** 1158 * {@inheritDoc} 1159 */ 1160 public boolean containsAttribute( AttributeType attributeType ) 1161 { 1162 if ( attributeType == null ) 1163 { 1164 return false; 1165 } 1166 1167 return attributes.containsKey( attributeType.getOid() ); 1168 } 1169 1170 1171 /** 1172 * {@inheritDoc} 1173 */ 1174 public boolean contains( AttributeType attributeType, byte[]... values ) 1175 { 1176 if ( attributeType == null ) 1177 { 1178 return false; 1179 } 1180 1181 Attribute attribute = attributes.get( attributeType.getOid() ); 1182 1183 if ( attribute != null ) 1184 { 1185 return attribute.contains( values ); 1186 } 1187 else 1188 { 1189 return false; 1190 } 1191 } 1192 1193 1194 /** 1195 * {@inheritDoc} 1196 */ 1197 public boolean contains( AttributeType attributeType, String... values ) 1198 { 1199 if ( attributeType == null ) 1200 { 1201 return false; 1202 } 1203 1204 Attribute attribute = attributes.get( attributeType.getOid() ); 1205 1206 if ( attribute != null ) 1207 { 1208 return attribute.contains( values ); 1209 } 1210 else 1211 { 1212 return false; 1213 } 1214 } 1215 1216 1217 /** 1218 * {@inheritDoc} 1219 */ 1220 public boolean contains( AttributeType attributeType, Value<?>... values ) 1221 { 1222 if ( attributeType == null ) 1223 { 1224 return false; 1225 } 1226 1227 Attribute attribute = attributes.get( attributeType.getOid() ); 1228 1229 if ( attribute != null ) 1230 { 1231 return attribute.contains( values ); 1232 } 1233 else 1234 { 1235 return false; 1236 } 1237 } 1238 1239 1240 /** 1241 * {@inheritDoc} 1242 */ 1243 public boolean contains( String upId, byte[]... values ) 1244 { 1245 if ( Strings.isEmpty( upId ) ) 1246 { 1247 return false; 1248 } 1249 1250 String id = getId( upId ); 1251 1252 if ( schemaManager != null ) 1253 { 1254 try 1255 { 1256 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1257 } 1258 catch ( LdapException le ) 1259 { 1260 return false; 1261 } 1262 } 1263 1264 Attribute attribute = attributes.get( id ); 1265 1266 if ( attribute == null ) 1267 { 1268 return false; 1269 } 1270 1271 return attribute.contains( values ); 1272 } 1273 1274 1275 /** 1276 * {@inheritDoc} 1277 */ 1278 public boolean contains( String upId, String... values ) 1279 { 1280 if ( Strings.isEmpty( upId ) ) 1281 { 1282 return false; 1283 } 1284 1285 String id = getId( upId ); 1286 1287 if ( schemaManager != null ) 1288 { 1289 try 1290 { 1291 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1292 } 1293 catch ( LdapException le ) 1294 { 1295 return false; 1296 } 1297 } 1298 1299 Attribute attribute = attributes.get( id ); 1300 1301 if ( attribute == null ) 1302 { 1303 return false; 1304 } 1305 1306 return attribute.contains( values ); 1307 } 1308 1309 1310 /** 1311 * {@inheritDoc} 1312 */ 1313 public boolean contains( String upId, Value<?>... values ) 1314 { 1315 if ( Strings.isEmpty( upId ) ) 1316 { 1317 return false; 1318 } 1319 1320 String id = getId( upId ); 1321 1322 if ( schemaManager != null ) 1323 { 1324 try 1325 { 1326 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1327 } 1328 catch ( LdapException le ) 1329 { 1330 return false; 1331 } 1332 } 1333 1334 Attribute attribute = attributes.get( id ); 1335 1336 if ( attribute == null ) 1337 { 1338 return false; 1339 } 1340 1341 return attribute.contains( values ); 1342 } 1343 1344 1345 /** 1346 * {@inheritDoc} 1347 */ 1348 public Attribute get( String alias ) 1349 { 1350 try 1351 { 1352 String id = getId( alias ); 1353 1354 if ( schemaManager != null ) 1355 { 1356 try 1357 { 1358 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 1359 1360 return attributes.get( attributeType.getOid() ); 1361 } 1362 catch ( LdapException ne ) 1363 { 1364 String message = ne.getLocalizedMessage(); 1365 LOG.error( message ); 1366 return null; 1367 } 1368 } 1369 else 1370 { 1371 return attributes.get( id ); 1372 } 1373 } 1374 catch ( IllegalArgumentException iea ) 1375 { 1376 LOG.error( I18n.err( I18n.ERR_04134, alias ) ); 1377 return null; 1378 } 1379 } 1380 1381 1382 /** 1383 * {@inheritDoc} 1384 */ 1385 public Attribute get( AttributeType attributeType ) 1386 { 1387 if ( attributeType != null ) 1388 { 1389 return attributes.get( attributeType.getOid() ); 1390 } 1391 else 1392 { 1393 return null; 1394 } 1395 } 1396 1397 1398 /** 1399 * {@inheritDoc} 1400 */ 1401 public Collection<Attribute> getAttributes() 1402 { 1403 return Collections.unmodifiableMap( attributes ).values(); 1404 } 1405 1406 1407 /** 1408 * {@inheritDoc} 1409 */ 1410 public Attribute put( String upId, byte[]... values ) 1411 { 1412 if ( Strings.isEmpty( upId ) ) 1413 { 1414 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 1415 LOG.error( message ); 1416 throw new IllegalArgumentException( message ); 1417 } 1418 1419 if ( schemaManager == null ) 1420 { 1421 // Get the normalized form of the ID 1422 String id = getId( upId ); 1423 1424 // Create a new attribute 1425 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1426 1427 // Replace the previous one, and return it back 1428 return attributes.put( id, clientAttribute ); 1429 } 1430 else 1431 { 1432 try 1433 { 1434 return put( upId, getAttributeType( upId ), values ); 1435 } 1436 catch ( LdapException ne ) 1437 { 1438 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() ); 1439 LOG.error( message ); 1440 throw new IllegalArgumentException( message ); 1441 } 1442 } 1443 } 1444 1445 1446 /** 1447 * {@inheritDoc} 1448 */ 1449 public Attribute put( String upId, String... values ) 1450 { 1451 if ( Strings.isEmpty( upId ) ) 1452 { 1453 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 1454 LOG.error( message ); 1455 throw new IllegalArgumentException( message ); 1456 } 1457 1458 if ( schemaManager == null ) 1459 { 1460 // Get the normalized form of the ID 1461 String id = getId( upId ); 1462 1463 // Create a new attribute 1464 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1465 1466 // Replace the previous one, and return it back 1467 return attributes.put( id, clientAttribute ); 1468 } 1469 else 1470 { 1471 try 1472 { 1473 return put( upId, getAttributeType( upId ), values ); 1474 } 1475 catch ( LdapException ne ) 1476 { 1477 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() ); 1478 LOG.error( message ); 1479 throw new IllegalArgumentException( message ); 1480 } 1481 } 1482 } 1483 1484 1485 /** 1486 * {@inheritDoc} 1487 */ 1488 public Attribute put( String upId, Value<?>... values ) 1489 { 1490 if ( Strings.isEmpty( upId ) ) 1491 { 1492 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 1493 LOG.error( message ); 1494 throw new IllegalArgumentException( message ); 1495 } 1496 1497 if ( schemaManager == null ) 1498 { 1499 // Get the normalized form of the ID 1500 String id = getId( upId ); 1501 1502 // Create a new attribute 1503 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1504 1505 // Replace the previous one, and return it back 1506 return attributes.put( id, clientAttribute ); 1507 } 1508 else 1509 { 1510 try 1511 { 1512 return put( upId, getAttributeType( upId ), values ); 1513 } 1514 catch ( LdapException ne ) 1515 { 1516 String message = I18n.err( I18n.ERR_04464, upId, ne.getLocalizedMessage() ); 1517 LOG.error( message ); 1518 throw new IllegalArgumentException( message ); 1519 } 1520 } 1521 } 1522 1523 1524 /** 1525 * {@inheritDoc} 1526 ** 1527 public List<Attribute> set( AttributeType... attributeTypes ) 1528 { 1529 List<Attribute> removed = new ArrayList<Attribute>(); 1530 1531 // Now, loop on all the attributeType to add 1532 for ( AttributeType attributeType : attributeTypes ) 1533 { 1534 if ( attributeType == null ) 1535 { 1536 String message = I18n.err( I18n.ERR_04467 ); 1537 LOG.error( message ); 1538 continue; 1539 } 1540 1541 Attribute attribute = attributes.put( attributeType.getOid(), 1542 new DefaultAttribute( attributeType ) ); 1543 1544 if ( attribute != null ) 1545 { 1546 removed.add( attribute ); 1547 } 1548 } 1549 1550 if ( removed.size() == 0 ) 1551 { 1552 return null; 1553 } 1554 else 1555 { 1556 return removed; 1557 } 1558 } 1559 1560 1561 /** 1562 * {@inheritDoc} 1563 */ 1564 public List<Attribute> put( Attribute... attributes ) throws LdapException 1565 { 1566 // First, get the existing attributes 1567 List<Attribute> previous = new ArrayList<Attribute>(); 1568 1569 if ( schemaManager == null ) 1570 { 1571 for ( Attribute attribute : attributes ) 1572 { 1573 String id = attribute.getId(); 1574 1575 if ( containsAttribute( id ) ) 1576 { 1577 // Store the attribute and remove it from the list 1578 previous.add( get( id ) ); 1579 this.attributes.remove( id ); 1580 } 1581 1582 // add the new one 1583 this.attributes.put( id, attribute ); 1584 } 1585 } 1586 else 1587 { 1588 for ( Attribute attribute : attributes ) 1589 { 1590 if ( attribute == null ) 1591 { 1592 String message = I18n.err( I18n.ERR_04462 ); 1593 LOG.error( message ); 1594 throw new IllegalArgumentException( message ); 1595 } 1596 1597 if ( attribute.getAttributeType() == null ) 1598 { 1599 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 1600 attribute.apply( attributeType ); 1601 } 1602 1603 Attribute removed = this.attributes.put( attribute.getAttributeType().getOid(), attribute ); 1604 1605 if ( removed != null ) 1606 { 1607 previous.add( removed ); 1608 } 1609 } 1610 } 1611 1612 // return the previous attributes 1613 return previous; 1614 } 1615 1616 1617 /** 1618 * {@inheritDoc} 1619 */ 1620 public Attribute put( AttributeType attributeType, byte[]... values ) throws LdapException 1621 { 1622 return put( null, attributeType, values ); 1623 } 1624 1625 1626 /** 1627 * {@inheritDoc} 1628 */ 1629 public Attribute put( AttributeType attributeType, String... values ) throws LdapException 1630 { 1631 return put( null, attributeType, values ); 1632 } 1633 1634 1635 /** 1636 * {@inheritDoc} 1637 */ 1638 public Attribute put( AttributeType attributeType, Value<?>... values ) throws LdapException 1639 { 1640 return put( null, attributeType, values ); 1641 } 1642 1643 1644 /** 1645 * {@inheritDoc} 1646 */ 1647 public Attribute put( String upId, AttributeType attributeType, byte[]... values ) throws LdapException 1648 { 1649 if ( attributeType == null ) 1650 { 1651 try 1652 { 1653 attributeType = getAttributeType( upId ); 1654 } 1655 catch ( Exception e ) 1656 { 1657 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID ); 1658 LOG.error( message ); 1659 throw new IllegalArgumentException( message ); 1660 } 1661 } 1662 else 1663 { 1664 if ( !Strings.isEmpty( upId ) ) 1665 { 1666 AttributeType tempAT = getAttributeType( upId ); 1667 1668 if ( !tempAT.equals( attributeType ) ) 1669 { 1670 String message = I18n.err( I18n.ERR_04463, upId, attributeType ); 1671 LOG.error( message ); 1672 throw new IllegalArgumentException( message ); 1673 } 1674 } 1675 else 1676 { 1677 upId = getUpId( upId, attributeType ); 1678 } 1679 } 1680 1681 if ( attributeType.equals( objectClassAttributeType ) ) 1682 { 1683 String message = I18n.err( I18n.ERR_04461 ); 1684 LOG.error( message ); 1685 throw new UnsupportedOperationException( message ); 1686 } 1687 1688 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1689 1690 return attributes.put( attributeType.getOid(), attribute ); 1691 } 1692 1693 1694 /** 1695 * {@inheritDoc} 1696 */ 1697 public Attribute put( String upId, AttributeType attributeType, String... values ) throws LdapException 1698 { 1699 if ( attributeType == null ) 1700 { 1701 try 1702 { 1703 attributeType = getAttributeType( upId ); 1704 } 1705 catch ( Exception e ) 1706 { 1707 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID ); 1708 LOG.error( message ); 1709 throw new IllegalArgumentException( message ); 1710 } 1711 } 1712 else 1713 { 1714 if ( !Strings.isEmpty( upId ) ) 1715 { 1716 AttributeType tempAT = getAttributeType( upId ); 1717 1718 if ( !tempAT.equals( attributeType ) ) 1719 { 1720 String message = I18n.err( I18n.ERR_04463, upId, attributeType ); 1721 LOG.error( message ); 1722 throw new IllegalArgumentException( message ); 1723 } 1724 } 1725 else 1726 { 1727 upId = getUpId( upId, attributeType ); 1728 } 1729 } 1730 1731 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1732 1733 return attributes.put( attributeType.getOid(), attribute ); 1734 } 1735 1736 1737 /** 1738 * {@inheritDoc} 1739 */ 1740 public Attribute put( String upId, AttributeType attributeType, Value<?>... values ) throws LdapException 1741 { 1742 if ( attributeType == null ) 1743 { 1744 try 1745 { 1746 attributeType = getAttributeType( upId ); 1747 } 1748 catch ( Exception e ) 1749 { 1750 String message = I18n.err( I18n.ERR_04477_NO_VALID_AT_FOR_THIS_ID ); 1751 LOG.error( message ); 1752 throw new IllegalArgumentException( message ); 1753 } 1754 } 1755 else 1756 { 1757 if ( !Strings.isEmpty( upId ) ) 1758 { 1759 AttributeType tempAT = getAttributeType( upId ); 1760 1761 if ( !tempAT.equals( attributeType ) ) 1762 { 1763 String message = I18n.err( I18n.ERR_04463, upId, attributeType ); 1764 LOG.error( message ); 1765 throw new IllegalArgumentException( message ); 1766 } 1767 } 1768 else 1769 { 1770 upId = getUpId( upId, attributeType ); 1771 } 1772 } 1773 1774 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1775 1776 return attributes.put( attributeType.getOid(), attribute ); 1777 } 1778 1779 1780 /** 1781 * {@inheritDoc} 1782 */ 1783 public List<Attribute> remove( Attribute... attributes ) throws LdapException 1784 { 1785 List<Attribute> removedAttributes = new ArrayList<Attribute>(); 1786 1787 if ( schemaManager == null ) 1788 { 1789 for ( Attribute attribute : attributes ) 1790 { 1791 if ( containsAttribute( attribute.getId() ) ) 1792 { 1793 this.attributes.remove( attribute.getId() ); 1794 removedAttributes.add( attribute ); 1795 } 1796 } 1797 } 1798 else 1799 { 1800 for ( Attribute attribute : attributes ) 1801 { 1802 AttributeType attributeType = attribute.getAttributeType(); 1803 1804 if ( attributeType == null ) 1805 { 1806 String message = I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 1807 LOG.error( message ); 1808 throw new IllegalArgumentException( message ); 1809 } 1810 1811 if ( this.attributes.containsKey( attributeType.getOid() ) ) 1812 { 1813 this.attributes.remove( attributeType.getOid() ); 1814 removedAttributes.add( attribute ); 1815 } 1816 } 1817 } 1818 1819 return removedAttributes; 1820 } 1821 1822 1823 /** 1824 * {@inheritDoc} 1825 */ 1826 public boolean remove( AttributeType attributeType, byte[]... values ) throws LdapException 1827 { 1828 if ( attributeType == null ) 1829 { 1830 return false; 1831 } 1832 1833 try 1834 { 1835 Attribute attribute = attributes.get( attributeType.getOid() ); 1836 1837 if ( attribute == null ) 1838 { 1839 // Can't remove values from a not existing attribute ! 1840 return false; 1841 } 1842 1843 int nbOldValues = attribute.size(); 1844 1845 // Remove the values 1846 attribute.remove( values ); 1847 1848 if ( attribute.size() == 0 ) 1849 { 1850 // No mare values, remove the attribute 1851 attributes.remove( attributeType.getOid() ); 1852 1853 return true; 1854 } 1855 1856 return nbOldValues != attribute.size(); 1857 } 1858 catch ( IllegalArgumentException iae ) 1859 { 1860 LOG.error( I18n.err( I18n.ERR_04465, attributeType ) ); 1861 return false; 1862 } 1863 } 1864 1865 1866 /** 1867 * {@inheritDoc} 1868 */ 1869 public boolean remove( AttributeType attributeType, String... values ) throws LdapException 1870 { 1871 if ( attributeType == null ) 1872 { 1873 return false; 1874 } 1875 1876 try 1877 { 1878 Attribute attribute = attributes.get( attributeType.getOid() ); 1879 1880 if ( attribute == null ) 1881 { 1882 // Can't remove values from a not existing attribute ! 1883 return false; 1884 } 1885 1886 int nbOldValues = attribute.size(); 1887 1888 // Remove the values 1889 attribute.remove( values ); 1890 1891 if ( attribute.size() == 0 ) 1892 { 1893 // No mare values, remove the attribute 1894 attributes.remove( attributeType.getOid() ); 1895 1896 return true; 1897 } 1898 1899 return nbOldValues != attribute.size(); 1900 } 1901 catch ( IllegalArgumentException iae ) 1902 { 1903 LOG.error( I18n.err( I18n.ERR_04465, attributeType ) ); 1904 return false; 1905 } 1906 } 1907 1908 1909 /** 1910 * {@inheritDoc} 1911 */ 1912 public boolean remove( AttributeType attributeType, Value<?>... values ) throws LdapException 1913 { 1914 if ( attributeType == null ) 1915 { 1916 return false; 1917 } 1918 1919 try 1920 { 1921 Attribute attribute = attributes.get( attributeType.getOid() ); 1922 1923 if ( attribute == null ) 1924 { 1925 // Can't remove values from a not existing attribute ! 1926 return false; 1927 } 1928 1929 int nbOldValues = attribute.size(); 1930 1931 // Remove the values 1932 attribute.remove( values ); 1933 1934 if ( attribute.size() == 0 ) 1935 { 1936 // No mare values, remove the attribute 1937 attributes.remove( attributeType.getOid() ); 1938 1939 return true; 1940 } 1941 1942 return nbOldValues != attribute.size(); 1943 } 1944 catch ( IllegalArgumentException iae ) 1945 { 1946 LOG.error( I18n.err( I18n.ERR_04465, attributeType ) ); 1947 return false; 1948 } 1949 } 1950 1951 1952 /** 1953 * <p> 1954 * Removes the attribute with the specified AttributeTypes. 1955 * </p> 1956 * <p> 1957 * The removed attribute are returned by this method. 1958 * </p> 1959 * <p> 1960 * If there is no attribute with the specified AttributeTypes, 1961 * the return value is <code>null</code>. 1962 * </p> 1963 * 1964 * @param attributes the AttributeTypes to be removed 1965 * @return the removed attributes, if any, as a list; otherwise <code>null</code> 1966 */ 1967 public void removeAttributes( AttributeType... attributes ) 1968 { 1969 if ( ( attributes == null ) || ( attributes.length == 0 ) || ( schemaManager == null ) ) 1970 { 1971 return; 1972 } 1973 1974 for ( AttributeType attributeType : attributes ) 1975 { 1976 if ( attributeType == null ) 1977 { 1978 continue; 1979 } 1980 1981 this.attributes.remove( attributeType.getOid() ); 1982 } 1983 } 1984 1985 1986 /** 1987 * {@inheritDoc} 1988 */ 1989 public void removeAttributes( String... attributes ) 1990 { 1991 if ( attributes.length == 0 ) 1992 { 1993 return; 1994 } 1995 1996 if ( schemaManager == null ) 1997 { 1998 for ( String attribute : attributes ) 1999 { 2000 Attribute attr = get( attribute ); 2001 2002 if ( attr != null ) 2003 { 2004 this.attributes.remove( attr.getId() ); 2005 } 2006 else 2007 { 2008 String message = I18n.err( I18n.ERR_04137, attribute ); 2009 LOG.warn( message ); 2010 continue; 2011 } 2012 } 2013 } 2014 else 2015 { 2016 for ( String attribute : attributes ) 2017 { 2018 AttributeType attributeType = null; 2019 2020 try 2021 { 2022 attributeType = schemaManager.lookupAttributeTypeRegistry( attribute ); 2023 } 2024 catch ( LdapException ne ) 2025 { 2026 String message = "The attribute '" + attribute + "' does not exist in the entry"; 2027 LOG.warn( message ); 2028 continue; 2029 } 2030 2031 this.attributes.remove( attributeType.getOid() ); 2032 } 2033 } 2034 } 2035 2036 2037 /** 2038 * <p> 2039 * Removes the specified binary values from an attribute. 2040 * </p> 2041 * <p> 2042 * If at least one value is removed, this method returns <code>true</code>. 2043 * </p> 2044 * <p> 2045 * If there is no more value after having removed the values, the attribute 2046 * will be removed too. 2047 * </p> 2048 * <p> 2049 * If the attribute does not exist, nothing is done and the method returns 2050 * <code>false</code> 2051 * </p> 2052 * 2053 * @param upId The attribute ID 2054 * @param values the values to be removed 2055 * @return <code>true</code> if at least a value is removed, <code>false</code> 2056 * if not all the values have been removed or if the attribute does not exist. 2057 */ 2058 public boolean remove( String upId, byte[]... values ) throws LdapException 2059 { 2060 if ( Strings.isEmpty( upId ) ) 2061 { 2062 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 2063 LOG.info( message ); 2064 return false; 2065 } 2066 2067 if ( schemaManager == null ) 2068 { 2069 String id = getId( upId ); 2070 2071 Attribute attribute = get( id ); 2072 2073 if ( attribute == null ) 2074 { 2075 // Can't remove values from a not existing attribute ! 2076 return false; 2077 } 2078 2079 int nbOldValues = attribute.size(); 2080 2081 // Remove the values 2082 attribute.remove( values ); 2083 2084 if ( attribute.size() == 0 ) 2085 { 2086 // No mare values, remove the attribute 2087 attributes.remove( id ); 2088 2089 return true; 2090 } 2091 2092 return nbOldValues != attribute.size(); 2093 } 2094 else 2095 { 2096 try 2097 { 2098 AttributeType attributeType = getAttributeType( upId ); 2099 2100 return remove( attributeType, values ); 2101 } 2102 catch ( LdapException ne ) 2103 { 2104 LOG.error( I18n.err( I18n.ERR_04465, upId ) ); 2105 return false; 2106 } 2107 catch ( IllegalArgumentException iae ) 2108 { 2109 LOG.error( I18n.err( I18n.ERR_04466, upId ) ); 2110 return false; 2111 } 2112 } 2113 2114 } 2115 2116 2117 /** 2118 * <p> 2119 * Removes the specified String values from an attribute. 2120 * </p> 2121 * <p> 2122 * If at least one value is removed, this method returns <code>true</code>. 2123 * </p> 2124 * <p> 2125 * If there is no more value after having removed the values, the attribute 2126 * will be removed too. 2127 * </p> 2128 * <p> 2129 * If the attribute does not exist, nothing is done and the method returns 2130 * <code>false</code> 2131 * </p> 2132 * 2133 * @param upId The attribute ID 2134 * @param values the attributes to be removed 2135 * @return <code>true</code> if at least a value is removed, <code>false</code> 2136 * if not all the values have been removed or if the attribute does not exist. 2137 */ 2138 public boolean remove( String upId, String... values ) throws LdapException 2139 { 2140 if ( Strings.isEmpty( upId ) ) 2141 { 2142 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 2143 LOG.info( message ); 2144 return false; 2145 } 2146 2147 if ( schemaManager == null ) 2148 { 2149 String id = getId( upId ); 2150 2151 Attribute attribute = get( id ); 2152 2153 if ( attribute == null ) 2154 { 2155 // Can't remove values from a not existing attribute ! 2156 return false; 2157 } 2158 2159 int nbOldValues = attribute.size(); 2160 2161 // Remove the values 2162 attribute.remove( values ); 2163 2164 if ( attribute.size() == 0 ) 2165 { 2166 // No mare values, remove the attribute 2167 attributes.remove( id ); 2168 2169 return true; 2170 } 2171 2172 return nbOldValues != attribute.size(); 2173 } 2174 else 2175 { 2176 try 2177 { 2178 AttributeType attributeType = getAttributeType( upId ); 2179 2180 return remove( attributeType, values ); 2181 } 2182 catch ( LdapException ne ) 2183 { 2184 LOG.error( I18n.err( I18n.ERR_04465, upId ) ); 2185 return false; 2186 } 2187 catch ( IllegalArgumentException iae ) 2188 { 2189 LOG.error( I18n.err( I18n.ERR_04466, upId ) ); 2190 return false; 2191 } 2192 } 2193 } 2194 2195 2196 /** 2197 * <p> 2198 * Removes the specified values from an attribute. 2199 * </p> 2200 * <p> 2201 * If at least one value is removed, this method returns <code>true</code>. 2202 * </p> 2203 * <p> 2204 * If there is no more value after having removed the values, the attribute 2205 * will be removed too. 2206 * </p> 2207 * <p> 2208 * If the attribute does not exist, nothing is done and the method returns 2209 * <code>false</code> 2210 * </p> 2211 * 2212 * @param upId The attribute ID 2213 * @param values the attributes to be removed 2214 * @return <code>true</code> if at least a value is removed, <code>false</code> 2215 * if not all the values have been removed or if the attribute does not exist. 2216 */ 2217 public boolean remove( String upId, Value<?>... values ) throws LdapException 2218 { 2219 if ( Strings.isEmpty( upId ) ) 2220 { 2221 String message = I18n.err( I18n.ERR_04457_NULL_ATTRIBUTE_ID ); 2222 LOG.info( message ); 2223 return false; 2224 } 2225 2226 if ( schemaManager == null ) 2227 { 2228 String id = getId( upId ); 2229 2230 Attribute attribute = get( id ); 2231 2232 if ( attribute == null ) 2233 { 2234 // Can't remove values from a not existing attribute ! 2235 return false; 2236 } 2237 2238 int nbOldValues = attribute.size(); 2239 2240 // Remove the values 2241 attribute.remove( values ); 2242 2243 if ( attribute.size() == 0 ) 2244 { 2245 // No mare values, remove the attribute 2246 attributes.remove( id ); 2247 2248 return true; 2249 } 2250 2251 return nbOldValues != attribute.size(); 2252 } 2253 else 2254 { 2255 try 2256 { 2257 AttributeType attributeType = getAttributeType( upId ); 2258 2259 return remove( attributeType, values ); 2260 } 2261 catch ( LdapException ne ) 2262 { 2263 LOG.error( I18n.err( I18n.ERR_04465, upId ) ); 2264 return false; 2265 } 2266 catch ( IllegalArgumentException iae ) 2267 { 2268 LOG.error( I18n.err( I18n.ERR_04466, upId ) ); 2269 return false; 2270 } 2271 } 2272 } 2273 2274 2275 /** 2276 * Get this entry's Dn. 2277 * 2278 * @return The entry's Dn 2279 */ 2280 public Dn getDn() 2281 { 2282 return dn; 2283 } 2284 2285 2286 /** 2287 * {@inheritDoc} 2288 */ 2289 public void setDn( Dn dn ) 2290 { 2291 this.dn = dn; 2292 2293 // Rehash the object 2294 rehash(); 2295 } 2296 2297 2298 /** 2299 * {@inheritDoc} 2300 */ 2301 public void setDn( String dn ) throws LdapInvalidDnException 2302 { 2303 setDn( new Dn( dn ) ); 2304 } 2305 2306 2307 /** 2308 * Remove all the attributes for this entry. The Dn is not reset 2309 */ 2310 public void clear() 2311 { 2312 attributes.clear(); 2313 } 2314 2315 2316 /** 2317 * Returns an enumeration containing the zero or more attributes in the 2318 * collection. The behavior of the enumeration is not specified if the 2319 * attribute collection is changed. 2320 * 2321 * @return an enumeration of all contained attributes 2322 */ 2323 public Iterator<Attribute> iterator() 2324 { 2325 return Collections.unmodifiableMap( attributes ).values().iterator(); 2326 } 2327 2328 2329 /** 2330 * Returns the number of attributes. 2331 * 2332 * @return the number of attributes 2333 */ 2334 public int size() 2335 { 2336 return attributes.size(); 2337 } 2338 2339 2340 /** 2341 * This is the place where we serialize entries, and all theirs 2342 * elements. 2343 * <br/> 2344 * The structure used to store the entry is the following : 2345 * <ul> 2346 * <li> 2347 * <b>[Dn]</b> : If it's null, stores an empty Dn 2348 * </li> 2349 * <li> 2350 * <b>[attributes number]</b> : the number of attributes. 2351 * </li> 2352 * <li> 2353 * <b>[attribute]*</b> : each attribute, if we have some 2354 * </li> 2355 * </ul> 2356 * 2357 * {@inheritDoc} 2358 */ 2359 public void writeExternal( ObjectOutput out ) throws IOException 2360 { 2361 // First, the Dn 2362 if ( dn == null ) 2363 { 2364 // Write an empty Dn 2365 Dn.EMPTY_DN.writeExternal( out ); 2366 } 2367 else 2368 { 2369 // Write the Dn 2370 dn.writeExternal( out ); 2371 } 2372 2373 // Then the attributes. 2374 // Store the attributes' nulber first 2375 out.writeInt( attributes.size() ); 2376 2377 // Iterate through the keys. 2378 for ( Attribute attribute : attributes.values() ) 2379 { 2380 // Store the attribute 2381 attribute.writeExternal( out ); 2382 } 2383 2384 out.flush(); 2385 } 2386 2387 2388 /** 2389 * {@inheritDoc} 2390 */ 2391 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException 2392 { 2393 // Read the Dn 2394 dn = new Dn( schemaManager ); 2395 dn.readExternal( in ); 2396 2397 // Read the number of attributes 2398 int nbAttributes = in.readInt(); 2399 2400 // Read the attributes 2401 for ( int i = 0; i < nbAttributes; i++ ) 2402 { 2403 // Read each attribute 2404 Attribute attribute = new DefaultAttribute(); 2405 attribute.readExternal( in ); 2406 2407 if ( schemaManager != null ) 2408 { 2409 try 2410 { 2411 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 2412 attribute.apply( attributeType ); 2413 2414 attributes.put( attributeType.getOid(), attribute ); 2415 } 2416 catch ( LdapException le ) 2417 { 2418 String message = le.getLocalizedMessage(); 2419 LOG.error( message ); 2420 throw new IOException( message ); 2421 } 2422 } 2423 else 2424 { 2425 attributes.put( attribute.getId(), attribute ); 2426 } 2427 } 2428 } 2429 2430 2431 /** 2432 * Get the hash code of this ClientEntry. The Attributes will be sorted 2433 * before the comparison can be done. 2434 * 2435 * @see java.lang.Object#hashCode() 2436 * @return the instance's hash code 2437 */ 2438 public int hashCode() 2439 { 2440 if ( h == 0 ) 2441 { 2442 rehash(); 2443 } 2444 2445 return h; 2446 } 2447 2448 2449 /** 2450 * {@inheritDoc} 2451 */ 2452 public boolean hasObjectClass( String... objectClasses ) 2453 { 2454 if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) ) 2455 { 2456 return false; 2457 } 2458 2459 for ( String objectClass : objectClasses ) 2460 { 2461 if ( schemaManager != null ) 2462 { 2463 if ( !contains( objectClassAttributeType, objectClass ) ) 2464 { 2465 return false; 2466 } 2467 } 2468 else 2469 { 2470 if ( !contains( "objectclass", objectClass ) ) 2471 { 2472 return false; 2473 } 2474 } 2475 } 2476 2477 return true; 2478 } 2479 2480 2481 /** 2482 * {@inheritDoc} 2483 */ 2484 public boolean hasObjectClass( Attribute... objectClasses ) 2485 { 2486 if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) ) 2487 { 2488 return false; 2489 } 2490 2491 for ( Attribute objectClass : objectClasses ) 2492 { 2493 // We have to check that we are checking the ObjectClass attributeType 2494 if ( !objectClass.getAttributeType().equals( objectClassAttributeType ) ) 2495 { 2496 return false; 2497 } 2498 2499 Attribute attribute = attributes.get( objectClassAttributeType.getOid() ); 2500 2501 if ( attribute == null ) 2502 { 2503 // The entry does not have an ObjectClass attribute 2504 return false; 2505 } 2506 2507 for ( Value<?> value : objectClass ) 2508 { 2509 // Loop on all the values, and check if they are present 2510 if ( !attribute.contains( value.getString() ) ) 2511 { 2512 return false; 2513 } 2514 } 2515 } 2516 2517 return true; 2518 } 2519 2520 2521 /** 2522 * {@inheritDoc} 2523 */ 2524 public boolean isSchemaAware() 2525 { 2526 return schemaManager != null; 2527 } 2528 2529 2530 /** 2531 * @see Object#equals(Object) 2532 */ 2533 public boolean equals( Object o ) 2534 { 2535 // Short circuit 2536 if ( this == o ) 2537 { 2538 return true; 2539 } 2540 2541 if ( !( o instanceof Entry ) ) 2542 { 2543 return false; 2544 } 2545 2546 Entry other = ( Entry ) o; 2547 2548 // Both Dn must be equal 2549 if ( dn == null ) 2550 { 2551 if ( other.getDn() != null ) 2552 { 2553 return false; 2554 } 2555 } 2556 else 2557 { 2558 if ( !dn.equals( other.getDn() ) ) 2559 { 2560 return false; 2561 } 2562 } 2563 2564 // They must have the same number of attributes 2565 if ( size() != other.size() ) 2566 { 2567 return false; 2568 } 2569 2570 // Each attribute must be equal 2571 for ( Attribute attribute : other ) 2572 { 2573 if ( !attribute.equals( this.get( attribute.getId() ) ) ) 2574 { 2575 return false; 2576 } 2577 } 2578 2579 return true; 2580 } 2581 2582 2583 /** 2584 * @see Object#toString() 2585 */ 2586 public String toString() 2587 { 2588 return toString( "" ); 2589 } 2590 2591 2592 /** 2593 * {@inheritDoc} 2594 */ 2595 public String toString( String tabs ) 2596 { 2597 StringBuilder sb = new StringBuilder(); 2598 2599 sb.append( tabs ).append( "Entry\n" ); 2600 sb.append( tabs ).append( " dn" ); 2601 2602 if ( dn.isSchemaAware() ) 2603 { 2604 sb.append( "[n]" ); 2605 } 2606 2607 sb.append( ": " ); 2608 sb.append( dn.getName() ); 2609 sb.append( '\n' ); 2610 2611 // First dump the ObjectClass attribute 2612 if ( schemaManager != null ) 2613 { 2614 // First dump the ObjectClass attribute 2615 if ( containsAttribute( objectClassAttributeType.getOid() ) ) 2616 { 2617 Attribute objectClass = get( objectClassAttributeType ); 2618 2619 sb.append( objectClass.toString( tabs + " " ) ); 2620 } 2621 } 2622 else 2623 { 2624 if ( containsAttribute( "objectClass" ) ) 2625 { 2626 Attribute objectClass = get( "objectclass" ); 2627 2628 sb.append( objectClass.toString( tabs + " " ) ); 2629 } 2630 } 2631 2632 sb.append( '\n' ); 2633 2634 if ( attributes.size() != 0 ) 2635 { 2636 for ( Attribute attribute : attributes.values() ) 2637 { 2638 String id = attribute.getId(); 2639 2640 if ( schemaManager != null ) 2641 { 2642 AttributeType attributeType = schemaManager.getAttributeType( id ); 2643 2644 if ( attributeType == null ) 2645 { 2646 sb.append( tabs + "id: " + id ); 2647 } 2648 else if ( !attributeType.equals( objectClassAttributeType ) ) 2649 { 2650 sb.append( attribute.toString( tabs + " " ) ); 2651 sb.append( '\n' ); 2652 continue; 2653 } 2654 } 2655 else 2656 { 2657 if ( !id.equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) 2658 && !id.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) ) 2659 { 2660 sb.append( attribute.toString( tabs + " " ) ); 2661 sb.append( '\n' ); 2662 continue; 2663 } 2664 } 2665 } 2666 } 2667 2668 return sb.toString(); 2669 } 2670}