Author: elecharny Date: Thu Aug 14 16:12:09 2008 New Revision: 686082 URL: http://svn.apache.org/viewvc?rev=686082&view=rev Log: o Replaced some of the ServerUtils methods by direct calls to the equivalent methods in the Server Entry/Attribute/Modification classes o Completely reviewed the serialization of entries/attributes/values/Modifications/LdifEnties o Added tests for all those serialization o Used Externalizable,instead of Serializable o Added some missing Javadoc o Fixed some failing tests in ModifyDN class o Fixed the wrong LDIF in referrals tests o Removed a lot of references on Attribute(s) and JNDI objects o Removed the password wrom the LdapPrincipal serialized form Added: directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientModification.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientModificationTest.java Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerEntrySerializerTest.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerModificationTest.java directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerStringValueTest.java directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/AbstractState.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authz/AuthorizationServiceAsNonAdminIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ListIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ModifyContextIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ObjStateFactoryIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ReferralIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/operational/OperationalAttributeServiceIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SchemaPersistenceIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SchemaServiceIT.java directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SubschemaSubentryIT.java directory/apacheds/branches/bigbang/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerDirContext.java directory/apacheds/branches/bigbang/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractTestCase.java directory/apacheds/branches/bigbang/core-unit/src/main/java/org/apache/directory/server/core/unit/IntegrationUtils.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultCoreSession.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/authn/LdapPrincipal.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/ModifyOperationContext.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/PartitionFrame.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/sp/StoredProcExecutionManager.java directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java directory/apacheds/branches/bigbang/protocol-shared/src/main/java/org/apache/directory/server/protocol/shared/store/LdifFileLoader.java directory/apacheds/branches/bigbang/protocol-shared/src/main/java/org/apache/directory/server/protocol/shared/store/LdifLoadFilter.java directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/state/AbstractState.java directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/bind/BindIT.java directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/bind/SimpleBindIT.java directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/ModifyRdnIT.java directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/search/ReferralSearchIT.java directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java directory/apacheds/branches/bigbang/server-jndi/src/main/java/org/apache/directory/server/configuration/ApacheDS.java directory/apacheds/branches/bigbang/server-jndi/src/test/java/org/apache/directory/server/configuration/ApacheDSTest.java directory/apacheds/branches/bigbang/server-tools/src/main/java/org/apache/directory/server/tools/ImportCommand.java directory/apacheds/branches/bigbang/server-unit/src/main/java/org/apache/directory/server/unit/AbstractServerTest.java directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/AttributeTypeHolder.java directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/ObjectClassHolder.java directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Entry.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/EntryAttribute.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Modification.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/ModificationOperation.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValue.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientStringValue.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttribute.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntry.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifEntry.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/Position.java directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValueTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientStringValueTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttributeTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntryTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/AttributeUtilsTest.java Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java?rev=686082&r1=686081&r2=686082&view=diff ============================================================================== --- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java (original) +++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java Thu Aug 14 16:12:09 2008 @@ -20,6 +20,9 @@ package org.apache.directory.server.core.entry; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -27,8 +30,10 @@ import javax.naming.NamingException; +import org.apache.directory.shared.ldap.entry.Entry; import org.apache.directory.shared.ldap.entry.EntryAttribute; import org.apache.directory.shared.ldap.entry.Value; +import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry; import org.apache.directory.shared.ldap.name.LdapDN; import org.apache.directory.shared.ldap.schema.AttributeType; @@ -75,7 +80,7 @@ /** * @return the cloned Entry */ - public ServerEntry getClonedEntry() + public Entry getClonedEntry() { return clonedEntry; } @@ -399,6 +404,44 @@ } + public Entry toClientEntry() throws NamingException + { + // Copy the DN + Entry clientEntry = new DefaultClientEntry( clonedEntry.getDn() ); + + // Convert each attribute + for ( EntryAttribute clonedEntry:this ) + { + EntryAttribute clientAttribute = ((ServerAttribute)clonedEntry).toClientAttribute(); + clientEntry.add( clientAttribute ); + } + + return clientEntry; + } + + + /** + * @see java.io.Externalizable#readExternal(ObjectInput) + * + * We can't use this method for a ServerEntry + */ + public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException + { + throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" ); + } + + + /** + * @see java.io.Externalizable#writeExternal(ObjectOutput) + * + * We can't use this method for a ServerEntry + */ + public void writeExternal( ObjectOutput out ) throws IOException + { + throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" ); + } + + public ServerEntry clone() { return ( ServerEntry ) clonedEntry.clone(); @@ -676,9 +719,36 @@ return 0; } + public ServerEntry clone() { return new EmptyEntry( dn ); } + + + public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException + { + } + + + public void writeExternal( ObjectOutput out ) throws IOException + { + } + + + public Entry toClientEntry() throws NamingException + { + // Copy the DN + Entry clientEntry = new DefaultClientEntry( dn ); + + // Convert each attribute + for ( EntryAttribute serverAttribute:this ) + { + EntryAttribute clientAttribute = ((ServerAttribute)serverAttribute).toClientAttribute(); + clientEntry.add( clientAttribute ); + } + + return clientEntry; + } } } Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java?rev=686082&r1=686081&r2=686082&view=diff ============================================================================== --- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java (original) +++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java Thu Aug 14 16:12:09 2008 @@ -19,6 +19,10 @@ package org.apache.directory.server.core.entry; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + import javax.naming.NamingException; import javax.naming.directory.InvalidAttributeValueException; @@ -42,6 +46,8 @@ */ public final class DefaultServerAttribute extends DefaultClientAttribute implements ServerAttribute { + public static final long serialVersionUID = 1L; + /** logger for reporting errors that might not be handled properly upstream */ private static final Logger LOG = LoggerFactory.getLogger( DefaultServerAttribute.class ); @@ -49,9 +55,9 @@ private AttributeType attributeType; - // ----------------------------------------------------------------------- + //----------------------------------------------------------------------- // utility methods - // ----------------------------------------------------------------------- + //----------------------------------------------------------------------- /** * Private helper method used to set an UpId from an attributeType * @@ -71,381 +77,157 @@ } + //------------------------------------------------------------------------- + // Constructors + //------------------------------------------------------------------------- /** - *
- * Check if the current attribute type is of the expected attributeType - *
- *- * This method won't tell if the current attribute is a descendant of - * the attributeType. For instance, the "CN" serverAttribute will return - * false if we ask if it's an instance of "Name". - *
+ * + * Creates a new instance of DefaultServerAttribute, by copying + * another attribute, which can be a ClientAttribute. If the other + * attribute is a ServerAttribute, it will be copied. * - * @param attributeId The AttributeType ID to check - * @return True if the current attribute is of the expected attributeType - * @throws InvalidAttributeValueException If there is no AttributeType + * @param attributeType The attribute's type + * @param attribute The attribute to be copied */ - public boolean instanceOf( String attributeId ) throws InvalidAttributeValueException + public DefaultServerAttribute( AttributeType attributeType, EntryAttribute attribute ) { - String trimmedId = StringTools.trim( attributeId ); - - if ( StringTools.isEmpty( trimmedId ) ) - { - return false; - } - - String normId = StringTools.lowerCaseAscii( trimmedId ); - - for ( String name:attributeType.getNamesRef() ) + // Copy the common values. isHR is only available on a ServerAttribute + this.attributeType = attributeType; + this.id = attribute.getId(); + this.upId = attribute.getUpId(); + + if ( attribute instanceof ServerAttribute ) { - if ( normId.equalsIgnoreCase( name ) ) + isHR = attribute.isHR(); + + // Copy all the values + for ( Value> value:attribute ) { - return true; + add( value.clone() ); } } - - return normId.equalsIgnoreCase( attributeType.getOid() ); - } - - - /** - *- * Overload the {@link DefaultClientAttribute#setId(String)} method. - *
- *- * As the attributeType has already been set, we have to be sure that the - * argument is compatible with the attributeType's name. - *
- *- * If the given ID is not compatible with the attributeType's possible - * names, the previously loaded ID will be kept. - *
- * - * @param id The attribute ID - */ - public void setId( String id ) - { - if ( !StringTools.isEmpty( StringTools.trim( id ) ) ) + else { - if ( attributeType.getName() == null ) + + try { - // If the name is null, then we may have to store an OID - if ( OID.isOID( id ) && attributeType.getOid().equals( id ) ) - { - // Everything is fine, store the upId. - // This should not happen... - super.setId( id ); - } + isHR = attributeType.getSyntax().isHumanReadable(); } - else + catch ( NamingException ne ) { - // We have at least one name. Check that the normalized upId - // is one of those names. Otherwise, the upId may be an OID too. - // In this case, it must be equals to the attributeType OID. - String normId = StringTools.lowerCaseAscii( StringTools.trim( id ) ); - - for ( String atName:attributeType.getNamesRef() ) + // Do nothing : the syntax should always exist ... + } + + + // Copy all the values + for ( Value> clientValue:attribute ) + { + Value> serverValue = null; + + // We have to convert the value first + if ( clientValue instanceof ClientStringValue ) { - if ( atName.equalsIgnoreCase( normId ) ) + if ( isHR ) { - // Found ! We can store the upId and get out - super.setId( normId ); - return; + serverValue = new ServerStringValue( attributeType, (String)clientValue.get() ); + } + else + { + // We have to convert the value to a binary value first + serverValue = new ServerBinaryValue( attributeType, + StringTools.getBytesUtf8( (String)clientValue.get() ) ); } } - - // Last case, the UpId is an OID - if ( OID.isOID( normId ) && attributeType.getOid().equals( normId ) ) - { - // We have an OID : stores it - super.setUpId( normId ); - } - else + else if ( clientValue instanceof ClientBinaryValue ) { - // The id is incorrect : this is not allowed - throw new IllegalArgumentException( "The ID '" + id + "'is incompatible with the AttributeType's id '" + - attributeType.getName() + "'" ); + if ( isHR ) + { + // We have to convert the value to a String value first + serverValue = new ServerStringValue( attributeType, + StringTools.utf8ToString( (byte[])clientValue.get() ) ); + } + else + { + serverValue = new ServerBinaryValue( attributeType, (byte[])clientValue.get() ); + } } + + add( serverValue ); } } - else - { - throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" + - " value when trimmed" ); - } } + // maybe have some additional convenience constructors which take + // an initial value as a string or a byte[] /** - *- * Overload the {@link DefaultClientAttribute#setUpId(String)} method. - *
- *- * As the attributeType has already been set, we have to be sure that the - * argument is compatible with the attributeType's name. - *
- *- * If the given ID is not compatible with the attributeType's possible - * names, the previously loaded ID will be kept. - *
- * - * @param upId The attribute ID + * Create a new instance of a EntryAttribute, without ID nor value. + * + * @param attributeType the attributeType for the empty attribute added into the entry */ - public void setUpId( String upId ) + public DefaultServerAttribute( AttributeType attributeType ) { - if ( !StringTools.isEmpty( StringTools.trim( upId ) ) ) + if ( attributeType == null ) { - if ( attributeType.getName() == null ) - { - // If the name is null, then we may have to store an OID - if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) ) - { - // Everything is fine, store the upId. - // This should not happen... - super.setUpId( upId ); - - } - } - else - { - // We have at least one name. Check that the normalized upId - // is one of those names. Otherwise, the upId may be an OID too. - // In this case, it must be equals to the attributeType OID. - String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) ); - - for ( String atId:attributeType.getNamesRef() ) - { - if ( atId.equalsIgnoreCase( normUpId ) ) - { - // Found ! We can store the upId and get out - super.setUpId( upId ); - return; - } - } - - // Last case, the UpId is an OID - if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) ) - { - // We have an OID : stores it - super.setUpId( upId ); - } - } + throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); } + + setAttributeType( attributeType ); } - - + + /** - *- * Set the user provided ID. If we have none, the upId is assigned - * the attributetype's name. If it does not have any name, we will - * use the OID. - *
- *- * If we have an upId and an AttributeType, they must be compatible. : - * - if the upId is an OID, it must be the AttributeType's OID - * - otherwise, its normalized form must be equals to ones of - * the attributeType's names. - *
- *- * In any case, the ATtributeType will be changed. The caller is responsible for - * the present values to be compatoble with the new AttributeType. - *
- * - * @param upId The attribute ID - * @param attributeType The associated attributeType + * Create a new instance of a EntryAttribute, without value. + * + * @param upId the ID for the added attributeType + * @param attributeType the added AttributeType */ - public void setUpId( String upId, AttributeType attributeType ) + public DefaultServerAttribute( String upId, AttributeType attributeType ) { - if ( StringTools.isEmpty( StringTools.trim( upId ) ) ) + if ( attributeType == null ) { - super.setUpId( getUpId( attributeType ) ); - this.attributeType = attributeType; + String message = "The AttributeType parameter should not be null"; + LOG.error( message ); + throw new IllegalArgumentException( message ); } - else - { - String name = attributeType.getName(); - - if ( name == null ) - { - // If the name is null, then we may have to store an OID - if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) ) - { - // Everything is fine, store the upId. - super.setUpId( upId ); - this.attributeType = attributeType; - } - else - { - // We have a difference or the upId is not a valid OID : - // we will use the attributeTypeOID in this case. - LOG.warn( "The upID ({}) is not an OID or is different from the AttributeType OID({})", - upId, attributeType.getOid() ); - super.setUpId( attributeType.getOid() ); - this.attributeType = attributeType; - } - } - else - { - // We have at least one name. Check that the normalized upId - // is one of those names. Otherwise, the upId may be an OID too. - // In this case, it must be equals to the attributeType OID. - String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) ); - - for ( String atId:attributeType.getNamesRef() ) - { - if ( atId.equalsIgnoreCase( normUpId ) ) - { - // Found ! We can store the upId and get out - super.setUpId( upId ); - this.attributeType = attributeType; - return; - } - } - - // UpId was not found in names. It should be an OID, or if not, we - // will use the AttributeType name. - if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) ) - { - // We have an OID : stores it - super.setUpId( upId ); - this.attributeType = attributeType; - } - else - { - String message = "The upID (" + upId + ") is not an OID or is different from the AttributeType OID (" + - attributeType.getOid() + ")"; - // Not a valid OID : use the AttributeTypes OID name instead - LOG.error( message ); - throw new IllegalArgumentException( message ); - } - } - } - } - - - /** - *- * Set the attribute type associated with this ServerAttribute. - *
- *- * The current attributeType will be replaced. It is the responsibility of - * the caller to insure that the existing values are compatible with the new - * AttributeType - *
- * - * @param attributeType the attributeType associated with this entry attribute - */ - public void setAttributeType( AttributeType attributeType ) - { - if ( attributeType == null ) - { - throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); - } - - this.attributeType = attributeType; - setUpId( null, attributeType ); - - try - { - if ( attributeType.getSyntax().isHumanReadable() ) - { - isHR = true; - } - else - { - isHR = false; - } - } - catch ( NamingException ne ) - { - // If we have an exception while trying to get the Syntax for this attribute - // just set it as Binary - isHR = false; - } - } - - - /** - * Get the attribute type associated with this ServerAttribute. - * - * @return the attributeType associated with this entry attribute - */ - public AttributeType getAttributeType() - { - return attributeType; - } - - - // maybe have some additional convenience constructors which take - // an initial value as a string or a byte[] - /** - * Create a new instance of a EntryAttribute, without ID nor value. - * - * @param attributeType the attributeType for the empty attribute added into the entry - */ - public DefaultServerAttribute( AttributeType attributeType ) - { - if ( attributeType == null ) - { - throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); - } - - setAttributeType( attributeType ); - } - - - /** - * Create a new instance of a EntryAttribute, without value. - * - * @param upId the ID for the added attributeType - * @param attributeType the added AttributeType - */ - public DefaultServerAttribute( String upId, AttributeType attributeType ) - { - if ( attributeType == null ) - { - String message = "The AttributeType parameter should not be null"; - LOG.error( message ); - throw new IllegalArgumentException( message ); - } - - setAttributeType( attributeType ); - setUpId( upId ); - } - - - /** - * Doc me more! - * - * If the value does not correspond to the same attributeType, then it's - * wrapped value is copied into a new Value which uses the specified - * attributeType. - * - * @param attributeType the attribute type according to the schema - * @param vals an initial set of values for this attribute - */ - public DefaultServerAttribute( AttributeType attributeType, Value>... vals ) - { - this( null, attributeType, vals ); - } - - - /** - * Doc me more! - * - * If the value does not correspond to the same attributeType, then it's - * wrapped value is copied into a new Value which uses the specified - * attributeType. - * - * Otherwise, the value is stored, but as a reference. It's not a copy. - * - * @param upId the ID of the added attribute - * @param attributeType the attribute type according to the schema - * @param vals an initial set of values for this attribute - */ - public DefaultServerAttribute( String upId, AttributeType attributeType, Value>... vals ) - { - if ( attributeType == null ) + + setAttributeType( attributeType ); + setUpId( upId ); + } + + + /** + * Doc me more! + * + * If the value does not correspond to the same attributeType, then it's + * wrapped value is copied into a new Value which uses the specified + * attributeType. + * + * @param attributeType the attribute type according to the schema + * @param vals an initial set of values for this attribute + */ + public DefaultServerAttribute( AttributeType attributeType, Value>... vals ) + { + this( null, attributeType, vals ); + } + + + /** + * Doc me more! + * + * If the value does not correspond to the same attributeType, then it's + * wrapped value is copied into a new Value which uses the specified + * attributeType. + * + * Otherwise, the value is stored, but as a reference. It's not a copy. + * + * @param upId the ID of the added attribute + * @param attributeType the attribute type according to the schema + * @param vals an initial set of values for this attribute + */ + public DefaultServerAttribute( String upId, AttributeType attributeType, Value>... vals ) + { + if ( attributeType == null ) { throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); } @@ -520,70 +302,115 @@ } - /** - * Clone an attribute. All the element are duplicated, so a modification on - * the original object won't affect the cloned object, as a modification - * on the cloned object has no impact on the original object - * - * @return a clone of the current attribute - */ - public ServerAttribute clone() - { - // clone the structure by cloner the inherited class - ServerAttribute clone = (ServerAttribute)super.clone(); - - // We are done ! - return clone; - } - - + //------------------------------------------------------------------------- + // API + //------------------------------------------------------------------------- /** *- * Overload the ClientAttribte isHR method : we can't change this flag - * for a ServerAttribute, as the HR is already set using the AttributeType. - * Set the attribute to Human Readable or to Binary. + * Adds some values to this attribute. If the new values are already present in + * the attribute values, the method has no effect. *
- * - * @param isHRtrue for a Human Readable attribute,
- * false for a Binary attribute.
- */
- public void setHR( boolean isHR )
- {
- // Do nothing...
- }
-
-
- /**
* - * Checks to see if this attribute is valid along with the values it contains. + * The new values are added at the end of list of values. *
*- * An attribute is valid if : - *
+ * If the value's type is different from the attribute's type, + * the value is not added. + *
+ * It's the responsibility of the caller to check if the stored + * values are consistent with the attribute's type. + *+ * + * @param vals some new values to be added which may be null + * @return the number of added values, or 0 if none has been added */ - public boolean isValid() throws NamingException + public int add( byte[]... vals ) { - // First check if the attribute has more than one value - // if the attribute is supposed to be SINGLE_VALUE - if ( attributeType.isSingleValue() && ( values.size() > 1 ) ) - { - return false; - } - - for ( Value> value : values ) + if ( !isHR ) { - if ( ! value.isValid() ) + int nbAdded = 0; + + for ( byte[] val:vals ) { - return false; + Value> value = new ServerBinaryValue( attributeType, val ); + + try + { + value.normalize(); + } + catch( NamingException ne ) + { + // The value can't be normalized : we don't add it. + LOG.error( "The value '" + val + "' can't be normalized, it hasn't been added" ); + return 0; + } + + if ( add( value ) != 0 ) + { + nbAdded++; + } + else + { + LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" ); + } } + + return nbAdded; } + else + { + // We can't add Binary values into a String serverAttribute + return 0; + } + } - return true; - } + + /** + *
+ * Adds some values to this attribute. If the new values are already present in + * the attribute values, the method has no effect. + *
+ *+ * The new values are added at the end of list of values. + *
+ *+ * This method returns the number of values that were added. + *
+ * If the value's type is different from the attribute's type, + * the value is not added. + * + * @param vals some new values to be added which may be null + * @return the number of added values, or 0 if none has been added + */ + public int add( String... vals ) + { + if ( isHR ) + { + int nbAdded = 0; + + for ( String val:vals ) + { + if ( add( new ServerStringValue( attributeType, val ) ) != 0 ) + { + nbAdded++; + } + else + { + LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" ); + } + } + + return nbAdded; + } + else + { + // We can't add String values into a Binary serverAttribute + return 0; + } + } /** @@ -693,111 +520,101 @@ /** + * Remove all the values from this attribute type, including a + * null value. + */ + public void clear() + { + values.clear(); + } + + + /** *- * Adds some values to this attribute. If the new values are already present in - * the attribute values, the method has no effect. - *
- *
- * The new values are added at the end of list of values.
+ * Indicates whether all the specified values are attribute's values. If
+ * at least one value is not an attribute's value, this method will return
+ * false
*
- * This method returns the number of values that were added.
+ * If the Attribute is HR, this method will returns false
*
- * Adds some values to this attribute. If the new values are already present in - * the attribute values, the method has no effect. - *
- *- * The new values are added at the end of list of values. - *
- *
- * This method returns the number of values that were added.
+ * Indicates whether all the specified values are attribute's values. If
+ * at least one value is not an attribute's value, this method will return
+ * false
*
- * If the value's type is different from the attribute's type,
- * the value is not added.
+ * If the Attribute is not HR, this method will returns false
*
* - * @param vals some new values to be added which may be null - * @return the number of added values, or 0 if none has been added + * @param vals the values + * @return true if this attribute contains all the values, otherwise false */ - public int add( byte[]... vals ) + public boolean contains( String... vals ) { - if ( !isHR ) + if ( isHR ) { - int nbAdded = 0; - - for ( byte[] val:vals ) + // Iterate through all the values, and quit if we + // don't find one in the values + for ( String val:vals ) { - if ( add( new ServerBinaryValue( attributeType, val ) ) != 0 ) - { - nbAdded++; - } - else + ServerStringValue value = new ServerStringValue( attributeType, val ); + + if ( !values.contains( value ) ) { - LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" ); + return false; } } - return nbAdded; + return true; } else { - // We can't add Binary values into a String serverAttribute - return 0; + return false; } - } + } /** - * Remove all the values from this attribute type, including a - * null value. - */ - public void clear() - { - values.clear(); - } - - - /** *
* Indicates whether the specified values are some of the attribute's values. *
@@ -840,230 +657,667 @@ return false; } } - } - else - { - for ( Value> val:vals ) + } + else + { + for ( Value> val:vals ) + { + if ( val instanceof ClientBinaryValue ) + { + if ( !values.contains( val ) ) + { + return false; + } + } + else + { + // Not a Binary value + return false; + } + } + } + + return true; + } + + + /** + * Get the attribute type associated with this ServerAttribute. + * + * @return the attributeType associated with this entry attribute + */ + public AttributeType getAttributeType() + { + return attributeType; + } + + + /** + *+ * Check if the current attribute type is of the expected attributeType + *
+ *+ * This method won't tell if the current attribute is a descendant of + * the attributeType. For instance, the "CN" serverAttribute will return + * false if we ask if it's an instance of "Name". + *
+ * + * @param attributeId The AttributeType ID to check + * @return True if the current attribute is of the expected attributeType + * @throws InvalidAttributeValueException If there is no AttributeType + */ + public boolean instanceOf( String attributeId ) throws InvalidAttributeValueException + { + String trimmedId = StringTools.trim( attributeId ); + + if ( StringTools.isEmpty( trimmedId ) ) + { + return false; + } + + String normId = StringTools.lowerCaseAscii( trimmedId ); + + for ( String name:attributeType.getNamesRef() ) + { + if ( normId.equalsIgnoreCase( name ) ) + { + return true; + } + } + + return normId.equalsIgnoreCase( attributeType.getOid() ); + } + + + /** + *+ * Checks to see if this attribute is valid along with the values it contains. + *
+ *+ * An attribute is valid if : + *
true if all the values shave been removed from this attribute
+ */
+ public boolean remove( byte[]... vals )
+ {
+ if ( isHR )
+ {
+ return false;
+ }
+
+ boolean removed = true;
+
+ for ( byte[] val:vals )
+ {
+ ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
+ removed &= values.remove( value );
+ }
+
+ return removed;
+ }
+
+
+ /**
+ * @see EntryAttribute#remove(String...)
+ *
+ * @return true if all the values shave been removed from this attribute
+ */
+ public boolean remove( String... vals )
+ {
+ if ( !isHR )
+ {
+ return false;
+ }
+
+ boolean removed = true;
+
+ for ( String val:vals )
+ {
+ ServerStringValue value = new ServerStringValue( attributeType, val );
+ removed &= values.remove( value );
+ }
+
+ return removed;
+ }
+
+
+ /**
+ * @see EntryAttribute#remove(org.apache.directory.shared.ldap.entry.Value...)
+ *
+ * @return true if all the values shave been removed from this attribute
+ */
+ public boolean remove( Value>... vals )
+ {
+ boolean removed = true;
+
+ // Loop through all the values to remove. If one of
+ // them is not present, the method will return false.
+ // As the attribute may be HR or not, we have two separated treatments
+ if ( isHR )
+ {
+ for ( Value> val:vals )
+ {
+ if ( val instanceof ClientStringValue )
+ {
+ ServerStringValue ssv = new ServerStringValue( attributeType, (String)val.get() );
+ removed &= values.remove( ssv );
+ }
+ else if ( val instanceof ServerStringValue )
+ {
+ removed &= values.remove( val );
+ }
+ else
+ {
+ removed = false;
+ }
+ }
+ }
+ else
+ {
+ for ( Value> val:vals )
+ {
+ if ( val instanceof ClientBinaryValue )
+ {
+ ServerBinaryValue sbv = new ServerBinaryValue( attributeType, (byte[])val.get() );
+ removed &= values.remove( sbv );
+ }
+ else if ( val instanceof ServerBinaryValue )
+ {
+ removed &= values.remove( val );
+ }
+ else
+ {
+ removed = false;
+ }
+ }
+ }
+
+ return removed;
+ }
+
+
+
+ /**
+ * + * Set the attribute type associated with this ServerAttribute. + *
+ *+ * The current attributeType will be replaced. It is the responsibility of + * the caller to insure that the existing values are compatible with the new + * AttributeType + *
+ * + * @param attributeType the attributeType associated with this entry attribute + */ + public void setAttributeType( AttributeType attributeType ) + { + if ( attributeType == null ) + { + throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); + } + + this.attributeType = attributeType; + setUpId( null, attributeType ); + + try + { + if ( attributeType.getSyntax().isHumanReadable() ) + { + isHR = true; + } + else + { + isHR = false; + } + } + catch ( NamingException ne ) + { + // If we have an exception while trying to get the Syntax for this attribute + // just set it as Binary + isHR = false; + } + } + + + /** + *+ * Overload the ClientAttribte isHR method : we can't change this flag + * for a ServerAttribute, as the HR is already set using the AttributeType. + * Set the attribute to Human Readable or to Binary. + *
+ * + * @param isHRtrue for a Human Readable attribute,
+ * false for a Binary attribute.
+ */
+ public void setHR( boolean isHR )
+ {
+ // Do nothing...
+ }
+
+
+ /**
+ * + * Overload the {@link DefaultClientAttribute#setId(String)} method. + *
+ *+ * As the attributeType has already been set, we have to be sure that the + * argument is compatible with the attributeType's name. + *
+ *+ * If the given ID is not compatible with the attributeType's possible + * names, the previously loaded ID will be kept. + *
+ * + * @param id The attribute ID + */ + public void setId( String id ) + { + if ( !StringTools.isEmpty( StringTools.trim( id ) ) ) + { + if ( attributeType.getName() == null ) + { + // If the name is null, then we may have to store an OID + if ( OID.isOID( id ) && attributeType.getOid().equals( id ) ) + { + // Everything is fine, store the upId. + // This should not happen... + super.setId( id ); + } + } + else + { + // We have at least one name. Check that the normalized upId + // is one of those names. Otherwise, the upId may be an OID too. + // In this case, it must be equals to the attributeType OID. + String normId = StringTools.lowerCaseAscii( StringTools.trim( id ) ); + + for ( String atName:attributeType.getNamesRef() ) + { + if ( atName.equalsIgnoreCase( normId ) ) + { + // Found ! We can store the upId and get out + super.setId( normId ); + return; + } + } + + // Last case, the UpId is an OID + if ( OID.isOID( normId ) && attributeType.getOid().equals( normId ) ) + { + // We have an OID : stores it + super.setUpId( normId ); + } + else + { + // The id is incorrect : this is not allowed + throw new IllegalArgumentException( "The ID '" + id + "'is incompatible with the AttributeType's id '" + + attributeType.getName() + "'" ); + } + } + } + else + { + throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" + + " value when trimmed" ); + } + } + + + /** + *+ * Overload the {@link DefaultClientAttribute#setUpId(String)} method. + *
+ *+ * As the attributeType has already been set, we have to be sure that the + * argument is compatible with the attributeType's name. + *
+ *+ * If the given ID is not compatible with the attributeType's possible + * names, the previously loaded ID will be kept. + *
+ * + * @param upId The attribute ID + */ + public void setUpId( String upId ) + { + if ( !StringTools.isEmpty( StringTools.trim( upId ) ) ) + { + if ( attributeType.getName() == null ) + { + // If the name is null, then we may have to store an OID + if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) ) + { + // Everything is fine, store the upId. + // This should not happen... + super.setUpId( upId ); + + } + } + else + { + // We have at least one name. Check that the normalized upId + // is one of those names. Otherwise, the upId may be an OID too. + // In this case, it must be equals to the attributeType OID. + String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) ); + + for ( String atId:attributeType.getNamesRef() ) + { + if ( atId.equalsIgnoreCase( normUpId ) ) + { + // Found ! We can store the upId and get out + super.setUpId( upId ); + return; + } + } + + // Last case, the UpId is an OID + if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) ) + { + // We have an OID : stores it + super.setUpId( upId ); + } + } + } + } + + + /** + *+ * Set the user provided ID. If we have none, the upId is assigned + * the attributetype's name. If it does not have any name, we will + * use the OID. + *
+ *+ * If we have an upId and an AttributeType, they must be compatible. : + * - if the upId is an OID, it must be the AttributeType's OID + * - otherwise, its normalized form must be equals to ones of + * the attributeType's names. + *
+ *+ * In any case, the ATtributeType will be changed. The caller is responsible for + * the present values to be compatoble with the new AttributeType. + *
+ * + * @param upId The attribute ID + * @param attributeType The associated attributeType + */ + public void setUpId( String upId, AttributeType attributeType ) + { + if ( StringTools.isEmpty( StringTools.trim( upId ) ) ) + { + super.setUpId( getUpId( attributeType ) ); + this.attributeType = attributeType; + } + else + { + String name = attributeType.getName(); + + if ( name == null ) + { + // If the name is null, then we may have to store an OID + if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) ) + { + // Everything is fine, store the upId. + super.setUpId( upId ); + this.attributeType = attributeType; + } + else + { + // We have a difference or the upId is not a valid OID : + // we will use the attributeTypeOID in this case. + LOG.warn( "The upID ({}) is not an OID or is different from the AttributeType OID({})", + upId, attributeType.getOid() ); + super.setUpId( attributeType.getOid() ); + this.attributeType = attributeType; + } + } + else { - if ( val instanceof ClientBinaryValue ) + // We have at least one name. Check that the normalized upId + // is one of those names. Otherwise, the upId may be an OID too. + // In this case, it must be equals to the attributeType OID. + String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) ); + + for ( String atId:attributeType.getNamesRef() ) { - if ( !values.contains( val ) ) + if ( atId.equalsIgnoreCase( normUpId ) ) { - return false; + // Found ! We can store the upId and get out + super.setUpId( upId ); + this.attributeType = attributeType; + return; } } + + // UpId was not found in names. It should be an OID, or if not, we + // will use the AttributeType name. + if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) ) + { + // We have an OID : stores it + super.setUpId( upId ); + this.attributeType = attributeType; + } else { - // Not a Binary value - return false; + String message = "The upID (" + upId + ") is not an OID or is different from the AttributeType OID (" + + attributeType.getOid() + ")"; + // Not a valid OID : use the AttributeTypes OID name instead + LOG.error( message ); + throw new IllegalArgumentException( message ); } } } - - return true; } /** - *
- * Indicates whether all the specified values are attribute's values. If
- * at least one value is not an attribute's value, this method will return
- * false
- *
- * If the Attribute is not HR, this method will returns false
- *
- * Indicates whether all the specified values are attribute's values. If
- * at least one value is not an attribute's value, this method will return
- * false
- *
- * If the Attribute is HR, this method will returns false
- *
+ *
+ * This is the place where we serialize attributes, and all theirs
+ * elements.
+ *
+ * The inner structure is the same as the client attribute, but we can't call
+ * it as we won't be able to serialize the serverValues
*
- * @return true if all the values shave been removed from this attribute
*/
- public boolean remove( Value>... vals )
+ public void serialize( ObjectOutput out ) throws IOException
{
- boolean removed = true;
+ // Write the UPId (the id will be deduced from the upID)
+ out.writeUTF( upId );
- // Loop through all the values to remove. If one of
- // them is not present, the method will return false.
- // As the attribute may be HR or not, we have two separated treatments
- if ( isHR )
+ // Write the HR flag, if not null
+ if ( isHR != null )
{
- for ( Value> val:vals )
- {
- if ( val instanceof ClientStringValue )
- {
- ServerStringValue ssv = new ServerStringValue( attributeType, (String)val.get() );
- removed &= values.remove( ssv );
- }
- else if ( val instanceof ServerStringValue )
- {
- removed &= values.remove( val );
- }
- else
- {
- removed = false;
- }
- }
+ out.writeBoolean( true );
+ out.writeBoolean( isHR );
}
else
{
- for ( Value> val:vals )
+ out.writeBoolean( false );
+ }
+
+ // Write the number of values
+ out.writeInt( size() );
+
+ if ( size() > 0 )
+ {
+ // Write each value
+ for ( Value> value:values )
{
- if ( val instanceof ClientBinaryValue )
- {
- ServerBinaryValue sbv = new ServerBinaryValue( attributeType, (byte[])val.get() );
- removed &= values.remove( sbv );
- }
- else if ( val instanceof ServerBinaryValue )
+ // Write the value, using the correct method
+ if ( value instanceof ServerStringValue )
{
- removed &= values.remove( val );
+ ((ServerStringValue)value).serialize( out );
}
else
{
- removed = false;
+ ((ServerBinaryValue)value).serialize( out );
}
}
}
- return removed;
+ out.flush();
}
-
+
/**
- * @see EntryAttribute#remove(byte[]...)
+ * @see java.io.Externalizable#readExternal(ObjectInput)
*
- * @return true if all the values shave been removed from this attribute
+ * We can't use this method for a ServerAttribute, as we have to feed the value
+ * with an AttributeType object
*/
- public boolean remove( byte[]... vals )
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
{
- if ( isHR )
- {
- return false;
- }
-
- boolean removed = true;
-
- for ( byte[] val:vals )
- {
- ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
- removed &= values.remove( value );
- }
-
- return removed;
+ throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
}
-
-
+
+
/**
- * @see EntryAttribute#remove(String...)
- *
- * @return true if all the values shave been removed from this attribute
+ * @see Externalizable#readExternal(ObjectInput)
*/
- public boolean remove( String... vals )
+ public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
{
- if ( !isHR )
- {
- return false;
- }
+ // Read the ID and the UPId
+ upId = in.readUTF();
- boolean removed = true;
+ // Compute the id
+ setUpId( upId );
- for ( String val:vals )
+ // Read the HR flag, if not null
+ if ( in.readBoolean() )
{
- ServerStringValue value = new ServerStringValue( attributeType, val );
- removed &= values.remove( value );
+ isHR = in.readBoolean();
}
-
- return removed;
- }
+ // Read the number of values
+ int nbValues = in.readInt();
+ if ( nbValues > 0 )
+ {
+ for ( int i = 0; i < nbValues; i++ )
+ {
+ Value> value = null;
+
+ if ( isHR )
+ {
+ value = new ServerStringValue( attributeType );
+ ((ServerStringValue)value).deserialize( in );
+ }
+ else
+ {
+ value = new ServerBinaryValue( attributeType );
+ ((ServerBinaryValue)value).deserialize( in );
+ }
+
+ try
+ {
+ value.normalize();
+ }
+ catch ( NamingException ne )
+ {
+ // Do nothing...
+ }
+
+ values.add( value );
+ }
+ }
+ }
+
+
//-------------------------------------------------------------------------
- // Overloaded Object classes
+ // Overloaded Object class methods
//-------------------------------------------------------------------------
/**
- * The hashCode is based on the id, the isHR flag and
- * on the internal values.
- *
- * @see Object#hashCode()
+ * Clone an attribute. All the element are duplicated, so a modification on
+ * the original object won't affect the cloned object, as a modification
+ * on the cloned object has no impact on the original object
*
- * @return the instance's hash code
+ * @return a clone of the current attribute
*/
- public int hashCode()
+ public ServerAttribute clone()
{
- int h = super.hashCode();
-
- if ( attributeType != null )
- {
- h = h*17 + attributeType.hashCode();
- }
+ // clone the structure by cloner the inherited class
+ ServerAttribute clone = (ServerAttribute)super.clone();
- return h;
+ // We are done !
+ return clone;
}
@@ -1109,6 +1363,27 @@
/**
+ * The hashCode is based on the id, the isHR flag and
+ * on the internal values.
+ *
+ * @see Object#hashCode()
+ *
+ * @return the instance's hash code
+ */
+ public int hashCode()
+ {
+ int h = super.hashCode();
+
+ if ( attributeType != null )
+ {
+ h = h*17 + attributeType.hashCode();
+ }
+
+ return h;
+ }
+
+
+ /**
* @see Object#toString()
*
* @return A String representation of this instance