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