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