+ * Note that the upValue should not be null or empty, or resolved + * to an empty string after having trimmed it. + * + * @param upType The Usrr Provided type + * @param normType The normalized type + * @param upValue The User Provided value + * @param normValue The normalized value */ - public AttributeTypeAndValue( String upType, String type, Object upValue, Object value ) throws InvalidNameException + public AttributeTypeAndValue( String upType, String normType, Object upValue, Object normValue ) throws InvalidNameException { - if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) ) + String upTypeTrimmed = StringTools.trim( upType ); + String normTypeTrimmed = StringTools.trim( normType ); + + if ( StringTools.isEmpty( upTypeTrimmed ) ) { - log.error( "The type cannot be empty or null" ); - throw new InvalidNameException( "Null or empty type is not allowed" ); + if ( StringTools.isEmpty( normTypeTrimmed ) ) + { + String message = "The type cannot be empty or null"; + LOG.error( message ); + throw new InvalidNameException( message ); + } + else + { + // In this case, we will use the normType instead + this.normType = StringTools.lowerCaseAscii( normTypeTrimmed ); + this.upType = normType; + } } + else if ( StringTools.isEmpty( normTypeTrimmed ) ) + { + // In this case, we will use the upType instead + this.normType = StringTools.lowerCaseAscii( upTypeTrimmed ); + this.upType = upType; + } + else + { + this.normType = StringTools.lowerCaseAscii( normTypeTrimmed ); + this.upType = upType; + + } + - normType = StringTools.lowerCaseAscii( type.trim() ); - this.upType = upType; - this.upValue = upValue; - - if ( value instanceof String ) + if ( ( normValue == null ) || ( upValue == null ) ) { - this.value = StringTools.isEmpty( ( String ) value ) ? "" : value; + if ( normValue instanceof String ) + { + this.value = StringTools.isEmpty( ( String ) normValue ) ? "" : normValue; + } + else + { + this.value = normValue; + } + + if ( upValue instanceof String ) + { + this.upValue = StringTools.isEmpty( ( String ) upValue ) ? "" : upValue; + } + else + { + this.upValue = upValue; + } } else { - this.value = value; + + this.upValue = upValue; + + if ( normValue instanceof String ) + { + this.value = StringTools.isEmpty( ( String ) normValue ) ? "" : normValue; + } + else + { + this.value = normValue; + } } - upName = upType + '=' + upValue; + upName = this.upType + '=' + ( this.upValue == null ? "" : this.upValue ); start = 0; length = upName.length(); } @@ -162,22 +215,42 @@ /** - * Store the type + * Store a new type * - * @param type - * The AttributeTypeAndValue type + * @param upType The AttributeTypeAndValue User Provided type + * @param type The AttributeTypeAndValue type + * + * @throws InvalidNameException if the type or upType are empty or null. + * If the upName is invalid. */ public void setType( String upType, String type ) throws InvalidNameException { if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) ) { - log.error( "The type cannot be empty or null" ); - throw new InvalidNameException( "The AttributeTypeAndValue type cannot be null or empty " ); + String message = "The type cannot be empty or null"; + LOG.error( message ); + throw new InvalidNameException( message ); + } + + if ( StringTools.isEmpty( upType ) || StringTools.isEmpty( upType.trim() ) ) + { + String message = "The User Provided type cannot be empty or null"; + LOG.error( message ); + throw new InvalidNameException( message ); + } + + int equalPosition = upName.indexOf( '=' ); + + if ( equalPosition <= 1 ) + { + String message = "The User provided name does not contains an '='"; + LOG.error( message ); + throw new InvalidNameException( message ); } normType = type.trim().toLowerCase(); this.upType = upType; - upName = upType + upName.substring( upName.indexOf( '=' ) ); + upName = upType + upName.substring( equalPosition ); start = -1; length = upName.length(); } @@ -193,7 +266,7 @@ { if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) ) { - log.error( "The type cannot be empty or null" ); + LOG.error( "The type cannot be empty or null" ); throw new InvalidNameException( "The AttributeTypeAndValue type cannot be null or empty " ); } @@ -637,12 +710,7 @@ return true; } - if ( obj == null ) - { - return false; - } - - if ( obj.getClass() != this.getClass() ) + if ( !( obj instanceof AttributeTypeAndValue ) ) { return false; } @@ -665,12 +733,170 @@ } } - // Compare the value - return ( value == null ? - instance.value == null : - value.equals( instance.value ) ); + // Compare the values + if ( value == null ) + { + return instance.value == null; + } + else if ( value instanceof String ) + { + if ( instance.value instanceof String ) + { + return value.equals( instance.value ); + } + else + { + return false; + } + } + else if ( value instanceof byte[] ) + { + if ( instance.value instanceof byte[] ) + { + return Arrays.equals( (byte[])value, (byte[])instance.value ); + } + else + { + return false; + } + } + else + { + return false; + } } + + /** + * @see Externalizable#readExternal(ObjectInput)
+ * + * An AttributeTypeAndValue is composed of a type and a value. + * The data are stored following the structure : + * + *
+ * if the value is a String : + *
+ * if the value is binary : + *
+ */ + public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException + { + upName = in.readUTF(); + start = in.readInt(); + length = in.readInt(); + upType = in.readUTF(); + normType = in.readUTF(); + + boolean isHR = in.readBoolean(); + + if ( isHR ) + { + upValue = in.readUTF(); + value = in.readUTF(); + } + else + { + int upValueLength = in.readInt(); + upValue = new byte[upValueLength]; + in.readFully( (byte[])upValue ); + + int valueLength = in.readInt(); + value = new byte[valueLength]; + in.readFully( (byte[])value ); + } + } + + /** * A String representation of a AttributeTypeAndValue. * Modified: directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java URL: http://svn.apache.org/viewvc/directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java?rev=612325&r1=612324&r2=612325&view=diff ============================================================================== --- directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java (original) +++ directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java Tue Jan 15 16:33:09 2008 @@ -21,6 +21,10 @@ package org.apache.directory.shared.ldap.name; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; @@ -57,10 +61,10 @@ * * @author Apache Directory Project */ -public class LdapDN implements Name +public class LdapDN implements Name, Externalizable { /** The LoggerFactory used by this class */ - protected static final Logger log = LoggerFactory.getLogger( LdapDN.class ); + protected static final Logger LOG = LoggerFactory.getLogger( LdapDN.class ); /** * Declares the Serial Version Uid. @@ -406,7 +410,7 @@ if ( posn > rdns.size() ) { String message = "Impossible to get the position " + posn + ", the DN only has " + rdns.size() + " RDNs"; - log.error( message ); + LOG.error( message ); throw new ArrayIndexOutOfBoundsException( message ); } @@ -636,7 +640,7 @@ catch ( InvalidNameException e ) { e.printStackTrace(); - log.error( "Failed to parse RDN for name " + name.toString(), e ); + LOG.error( "Failed to parse RDN for name " + name.toString(), e ); return false; } @@ -833,7 +837,7 @@ { if ( pos >= rdns.size() ) { - log.error( "Exceeded number of elements in the current object" ); + LOG.error( "Exceeded number of elements in the current object" ); throw new NoSuchElementException(); } @@ -876,7 +880,7 @@ { if ( pos >= rdns.size() ) { - log.error( "Exceeded number of elements in the current object" ); + LOG.error( "Exceeded number of elements in the current object" ); throw new NoSuchElementException(); } @@ -912,7 +916,7 @@ if ( ( posn < 0 ) || ( posn > rdns.size() ) ) { String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"; - log.error( message ); + LOG.error( message ); throw new ArrayIndexOutOfBoundsException( message ); } @@ -956,7 +960,7 @@ if ( ( posn < 0 ) || ( posn > rdns.size() ) ) { String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"; - log.error( message ); + LOG.error( message ); throw new ArrayIndexOutOfBoundsException( message ); } @@ -1222,7 +1226,7 @@ if ( ( posn < 0 ) || ( posn > size() ) ) { String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"; - log.error( message ); + LOG.error( message ); throw new ArrayIndexOutOfBoundsException( message ); } @@ -1264,7 +1268,7 @@ if ( ( posn < 0 ) || ( posn >= rdns.size() ) ) { String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"; - log.error( message ); + LOG.error( message ); throw new ArrayIndexOutOfBoundsException( message ); } @@ -1301,7 +1305,7 @@ } catch ( CloneNotSupportedException cnse ) { - log.error( "The clone operation has failed" ); + LOG.error( "The clone operation has failed" ); throw new Error( "Assertion failure : cannot clone the object" ); } } @@ -1433,7 +1437,7 @@ else { // The type is empty : this is not possible... - log.error( "Empty type not allowed in a DN" ); + LOG.error( "Empty type not allowed in a DN" ); throw new InvalidNameException( "Empty type not allowed in a DN" ); } @@ -1538,7 +1542,7 @@ else { // The type is empty : this is not possible... - log.error( "We should not have an empty DN" ); + LOG.error( "We should not have an empty DN" ); throw new InvalidNameException( "Empty type not allowed in a DN" ); } } @@ -1655,5 +1659,130 @@ public boolean isNormalized() { return normalized; + } + + + /** + * @see Externalizable#readExternal(ObjectInput)
+ * + * We have to store a DN data efficiently. Here is the structure : + * + *
+ *
+ *
+ * + * for each rdn : + *
+ */
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+ {
+ // Read the UPName
+ upName = in.readUTF();
+
+ // Read the NormName
+ normName = in.readUTF();
+
+ if ( normName.length() == 0 )
+ {
+ // As the normName is equal to the upName,
+ // we didn't saved the nbnormName on disk.
+ // restore it by copying the upName.
+ normName = upName;
+ }
+
+ // A serialized DN is always normalized.
+ normalized = true;
+
+ // Should we read the byte[] ???
+ bytes = StringTools.getBytesUtf8( upName );
+
+ // Read the RDNs. Is it's null, the number will be -1.
+ int nbRdns = in.readInt();
+
+ switch ( nbRdns )
+ {
+ case -1 :
+ // No RDN at all...
+ rdns = null;
+ break;
+
+ case 0 :
+ // No RDN, but we have to initialize the list
+ // Note : this may not be a different case than -1
+ rdns = new ArrayList
+ * For each ATAV :
+ *
+ */
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+ {
+ // Read the ATAV number
+ nbAtavs = in.readInt();
+
+ // Read the UPName
+ upName = in.readUTF();
+
+ // Read the normName
+ normName = in.readUTF();
+
+ if ( StringTools.isEmpty( normName ) )
+ {
+ normName = upName;
+ }
+
+ start = in.readInt();
+ length = in.readInt();
+
+ switch ( nbAtavs )
+ {
+ case 0 :
+ atav = null;
+ break;
+
+ case 1 :
+ atav = (AttributeTypeAndValue)in.readObject();
+ atavType = atav.getNormType();
+
+ break;
+
+ default :
+ atavs = new TreeSet