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