From commits-return-6381-apmail-directory-commits-archive=directory.apache.org@directory.apache.org Sun Oct 09 13:47:29 2005 Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 65519 invoked from network); 9 Oct 2005 13:47:29 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 9 Oct 2005 13:47:29 -0000 Received: (qmail 98945 invoked by uid 500); 9 Oct 2005 13:47:29 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 98894 invoked by uid 500); 9 Oct 2005 13:47:29 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 98883 invoked by uid 99); 9 Oct 2005 13:47:29 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 09 Oct 2005 06:47:29 -0700 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Sun, 09 Oct 2005 06:47:31 -0700 Received: (qmail 65510 invoked by uid 65534); 9 Oct 2005 13:47:07 -0000 Message-ID: <20051009134707.65509.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r307428 - /directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java Date: Sun, 09 Oct 2005 13:47:07 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: elecharny Date: Sun Oct 9 06:47:02 2005 New Revision: 307428 URL: http://svn.apache.org/viewcvs?rev=307428&view=rev Log: Complete rewriting of this class. It extends Name, and use an external parser to analyse and construct a DN. Modified: directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java Modified: directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java URL: http://svn.apache.org/viewcvs/directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java?rev=307428&r1=307427&r2=307428&view=diff ============================================================================== --- directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java (original) +++ directory/shared/ldap/trunk/apache2-provider/src/java/main/org/apache/asn1new/ldap/codec/primitives/LdapDN.java Sun Oct 9 06:47:02 2005 @@ -14,7 +14,7 @@ * limitations under the License. * */ -package org.apache.asn1new.ldap.codec.primitives; +/*package org.apache.asn1new.ldap.codec.primitives; import java.io.UnsupportedEncodingException; @@ -50,19 +50,19 @@ *

* * @author Apache Directory Project - */ + * public class LdapDN extends RelativeLdapDN { //~ Static fields/initializers ----------------------------------------------------------------- - /** A null LdapDN */ + /** A null LdapDN * public transient static final LdapDN EMPTY_STRING = new LdapDN(); //~ Methods ------------------------------------------------------------------------------------ /** * Construct an empty LdapDN object - */ + * public LdapDN() { super(0, false); @@ -78,10 +78,9 @@ * * @param bytes The byte buffer that contains the DN * @exception A DecoderException is thrown if the buffer does not contains a valid DN. - */ + * public LdapDN( byte[] bytes ) throws DecoderException { - if ( bytes == null || bytes.length == 0) { return; @@ -125,5 +124,742 @@ } setData(bytes); + } +} +*/ + +package org.apache.asn1new.ldap.codec.primitives; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import javax.naming.InvalidNameException; +import javax.naming.Name; + +import org.apache.asn1new.util.StringUtils; + +/** + * + * @author Apache Directory Project + */ +public class LdapDN extends LdapString implements Name +{ + /** + * Declares the Serial Version Uid. + * + * @see Always Declare Serial Version Uid + */ + private static final long serialVersionUID = 1L; + + /** Value returned by the compareTo method if values are not equals */ + public final static int NOT_EQUALS = -1; + + /** Value returned by the compareTo method if values are equals */ + public final static int EQUALS = 0; + + //~ Static fields/initializers ----------------------------------------------------------------- + /** The RDNs that are elements of the DN */ + private List rdns = new ArrayList(5); + + /** A null LdapDN */ + public transient static final LdapDN EMPTY_LDAPDN = new LdapDN(); + + //~ Methods ------------------------------------------------------------------------------------ + + /** + * Construct an empty LdapDN object + */ + public LdapDN() + { + super(); + } + + /** + * Parse a String and checks that it is a valid DN
+ *

+ * <distinguishedName> ::= <name> | e
+ * <name> ::= <name-component> <name-components>
+ * <name-components> ::= <spaces> <separator> <spaces> <name-component> <name-components> | e
+ *

+ * + * @param bytes The byte buffer that contains the DN + * @exception A InvalidNameException is thrown if the buffer does not contains a valid DN. + */ + public LdapDN( String string ) throws InvalidNameException + { + if ( StringUtils.isNotEmpty( string ) ) + { + try + { + string.getBytes( "UTF-8" ); + } + catch ( UnsupportedEncodingException uee ) + { + throw new InvalidNameException( "The byte array is not an UTF-8 encoded Unicode String : " + uee.getMessage() ); + } + + DNParser.parse( string, rdns ); + } + else + { + this.string = ""; + } + + normalize(); + } + + /** + * Parse a buffer and checks that it is a valid DN
+ *

+ * <distinguishedName> ::= <name> | e
+ * <name> ::= <name-component> <name-components>
+ * <name-components> ::= <spaces> <separator> <spaces> <name-component> <name-components> | e
+ *

+ * + * @param bytes The byte buffer that contains the DN + * @exception A InvalidNameException is thrown if the buffer does not contains a valid DN. + */ + public LdapDN( byte[] bytes ) throws InvalidNameException + { + try + { + DNParser.parse( new String( bytes, "UTF-8" ), rdns ); + this.string = toString(); + normalize(); + } + catch ( UnsupportedEncodingException uee ) + { + throw new InvalidNameException( "The byte array is not an UTF-8 encoded Unicode String : " + uee.getMessage() ); + } + } + + + /** + * Normalize the DN by triming useless spaces and lowercasing names. + * @return a normalized form of the DN + */ + private void normalize() + { + StringBuffer sb = new StringBuffer(); + + if ( rdns == null ) + { + string = ""; + } + + Iterator elements = rdns.iterator(); + boolean isFirst = true; + + while ( elements.hasNext() ) + { + LdapRDN rdn = (LdapRDN)elements.next(); + + if ( isFirst ) + { + isFirst = false; + } + else + { + sb.append(','); + } + + sb.append( rdn.toString() ); + } + + string = sb.toString(); + + try + { + bytes = string.getBytes( "UTF-8" ); + } + catch ( UnsupportedEncodingException uee ) + { + // We can't reach this point + } + } + + /** + * Return the DN as a String + * @return A String representing the DN + */ + public String toString() + { + if ( ( rdns == null ) || ( rdns.size() == 0 ) ) + { + return ""; + } + else + { + StringBuffer sb = new StringBuffer(); + boolean isFirst = true; + + for ( int i = 0; i < rdns.size(); i++ ) + { + if ( isFirst ) + { + isFirst = false; + } + else + { + sb.append( ',' ); + } + + sb.append( ( (LdapRDN)rdns.get( i ) ) ); + } + + return sb.toString(); + } + } + + /** + * Get the initial DN (without normalization) + * @return The DN as a String + */ + public String getName() + { + return ( string == null ? "" : string ); + } + + /** + * Get the number of NameComponent conatained in this LdapDN + * + * @return The number of NameComponent conatained in this LdapDN + */ + public int size() + { + return rdns.size(); + } + + /** + * Determines whether this name starts with a specified prefix. + * A name name is a prefix if it is equal to + * getPrefix(name.size()). + * + * Be aware that for a specific DN like : + * + * cn=xxx, ou=yyy + * + * the startsWith method will retourn true with ou=yyy, and + * false with cn=xxx + * + * @param name the name to check + * @return true if name is a prefix of this name, false otherwise + */ + public boolean startsWith ( Name name ) + { + if ( name instanceof LdapDN ) + { + LdapDN nameDN = (LdapDN)name; + + if ( nameDN.size() == 0 ) + { + return true; + } + + if ( nameDN.size() > size() ) + { + // The name is longer than the current LdapDN. + return false; + } + + // Ok, iterate through all the RDN of the name, + // starting a the end of the current list. + + for ( int i = nameDN.size() - 1; i >= 0; i-- ) + { + LdapRDN nameRdn = (LdapRDN)(nameDN.rdns.get( nameDN.rdns.size() - i - 1 )); + LdapRDN ldapRdn = (LdapRDN)rdns.get( rdns.size() - i - 1 ); + + if ( nameRdn.compareTo(ldapRdn) != 0 ) + { + return false; + } + } + + return true; + } + else + { + // We don't accept a Name which is not a LdapName + return name == null; + } + } + + /** + * Determines whether this name ends with a specified suffix. + * A name name is a suffix if it is equal to + * getSuffix(size()-name.size()). + * + * Be aware that for a specific DN like : + * + * cn=xxx, ou=yyy + * + * the endsWith method will retourn true with cn=xxx, and + * false with ou=yyy + * + * @param name the name to check + * @return true if name is a suffix of this name, false otherwise + */ + public boolean endsWith ( Name name ) + { + if ( name instanceof LdapDN ) + { + LdapDN nameDN = (LdapDN)name; + + if ( nameDN.size() == 0 ) + { + return true; + } + + if ( nameDN.size() > size() ) + { + // The name is longer than the current LdapDN. + return false; + } + + // Ok, iterate through all the RDN of the name + for ( int i = 0; i < nameDN.size(); i++ ) + { + LdapRDN nameRdn = (LdapRDN)(nameDN.rdns.get( i )); + LdapRDN ldapRdn = (LdapRDN)rdns.get( i ); + + if ( nameRdn.compareTo(ldapRdn) != 0 ) + { + return false; + } + } + + return true; + } + else + { + // We don't accept a Name which is not a LdapName + return name == null; + } + } + + /** + * Determines whether this name is empty. + * An empty name is one with zero components. + * + * @return true if this name is empty, false otherwise + */ + public boolean isEmpty() + { + return ( rdns.size() == 0 ); + } + + /** + * Retrieves a component of this name. + * + * @param posn + * the 0-based index of the component to retrieve. + * Must be in the range [0,size()). + * @return the component at index posn + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + */ + public String get( int posn ) + { + if ( rdns.size() == 0 ) + { + return ""; + } + else + { + LdapRDN rdn = (LdapRDN)rdns.get( rdns.size() - posn - 1 ); + + return rdn.toString(); + } + } + + /** + * Retrieves the components of this name as an enumeration + * of strings. The effect on the enumeration of updates to + * this name is undefined. If the name has zero components, + * an empty (non-null) enumeration is returned. + * + * @return an enumeration of the components of this name, each a string + */ + public Enumeration getAll() + { + /* + * Note that by accessing the name component using the get() method on + * the name rather than get() on the list we are reading components from + * right to left with increasing index values. LdapName.get() does the + * index translation on m_list for us. + */ + return new Enumeration() + { + private int pos ; + + public boolean hasMoreElements() + { + return pos < rdns.size() ; + } + + public Object nextElement() + { + if ( pos >= rdns.size() ) + { + throw new NoSuchElementException() ; + } + + Object obj = get( pos ) ; + pos++ ; + return obj ; + } + }; + } + + /** + * Creates a name whose components consist of a prefix of the + * components of this name. Subsequent changes to + * this name will not affect the name that is returned and vice versa. + * + * @param posn + * the 0-based index of the component at which to stop. + * Must be in the range [0,size()]. + * @return a name consisting of the components at indexes in + * the range [0,posn]. + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + */ + public Name getPrefix( int posn ) + { + if ( rdns.size() == 0 ) + { + return EMPTY_LDAPDN; + } + + if ( ( posn < 0 ) || ( posn > rdns.size() ) ) + { + throw new ArrayIndexOutOfBoundsException("The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"); + } + + LdapDN newLdapDN = new LdapDN(); + + for (int i = rdns.size() - posn; i < rdns.size(); i++ ) + { + // Don't forget to clone the rdns ! + newLdapDN.rdns.add( ( (LdapRDN)rdns.get( i ) ).clone() ); + } + + newLdapDN.normalize(); + newLdapDN.string = newLdapDN.toString(); + + return newLdapDN; + } + + /** + * Creates a name whose components consist of a suffix of the + * components in this name. Subsequent changes to + * this name do not affect the name that is returned and vice versa. + * + * @param posn + * the 0-based index of the component at which to start. + * Must be in the range [0,size()]. + * @return a name consisting of the components at indexes in + * the range [posn,size()]. If posn is equal to + * size(), an empty name is returned. + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + */ + public Name getSuffix( int posn ) + { + if ( rdns.size() == 0 ) + { + return EMPTY_LDAPDN; + } + + if ( ( posn < 0 ) || ( posn > rdns.size() ) ) + { + throw new ArrayIndexOutOfBoundsException("The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"); + } + + LdapDN newLdapDN = new LdapDN(); + + for (int i = 0; i < size() - posn; i++ ) + { + // Don't forget to clone the rdns ! + newLdapDN.rdns.add( ( (LdapRDN)rdns.get( i ) ).clone() ); + } + + newLdapDN.normalize(); + newLdapDN.string = newLdapDN.toString(); + + return newLdapDN; + } + /** + * Adds the components of a name -- in order -- to the end of this name. + * + * @param suffix + * the components to add + * @return the updated name (not a new one) + * + * @throws InvalidNameException if suffix is not a valid name, + * or if the addition of the components would violate the syntax + * rules of this name + */ + public Name addAll( Name suffix ) throws InvalidNameException + { + addAll( rdns.size(), suffix ); + + return this; + } + + /** + * Adds the components of a name -- in order -- at a specified position + * within this name. + * Components of this name at or after the index of the first new + * component are shifted up (away from 0) to accommodate the new + * components. + * + * @param name + * the components to add + * @param posn + * the index in this name at which to add the new + * components. Must be in the range [0,size()]. + * @return the updated name (not a new one) + * + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + * @throws InvalidNameException if n is not a valid name, + * or if the addition of the components would violate the syntax + * rules of this name + */ + public Name addAll(int posn, Name name) throws InvalidNameException + { + if (name instanceof LdapDN ) + { + if ( ( name == null ) || ( name.size() == 0 ) ) + { + return this; + } + + // Concatenate the rdns + rdns.addAll( size() - posn, ((LdapDN)name).rdns ); + + // Regenerate the normalized name and the original string + normalize(); + + return this; + } + else + { + throw new InvalidNameException( "The suffix is not a LdapDN" ); + } + } + + /** + * Adds a single component to the end of this name. + * + * @param comp + * the component to add + * @return the updated name (not a new one) + * + * @throws InvalidNameException if adding comp would violate + * the syntax rules of this name + */ + public Name add(String comp) throws InvalidNameException + { + // We have to parse the nameComponent which is given as an argument + LdapRDN newRdn = new LdapRDN( comp ); + + rdns.add( 0, newRdn ); + normalize(); + + return this; + } + + /** + * Adds a single component at a specified position within this name. + * Components of this name at or after the index of the new component + * are shifted up by one (away from index 0) to accommodate the new + * component. + * + * @param comp + * the component to add + * @param posn + * the index at which to add the new component. + * Must be in the range [0,size()]. + * @return the updated name (not a new one) + * + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + * @throws InvalidNameException if adding comp would violate + * the syntax rules of this name + */ + public Name add(int posn, String comp) throws InvalidNameException + { + if ( ( posn < 0 ) || ( posn > size() ) ) + { + throw new ArrayIndexOutOfBoundsException("The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"); + } + + // We have to parse the nameComponent which is given as an argument + LdapRDN newRdn = new LdapRDN( comp ); + + int realPos = size() - posn; + rdns.add( realPos, newRdn ); + normalize(); + + return this; + } + + /** + * Removes a component from this name. + * The component of this name at the specified position is removed. + * Components with indexes greater than this position + * are shifted down (toward index 0) by one. + * + * @param posn + * the index of the component to remove. + * Must be in the range [0,size()). + * @return the component removed (a String) + * + * @throws ArrayIndexOutOfBoundsException + * if posn is outside the specified range + * @throws InvalidNameException if deleting the component + * would violate the syntax rules of the name + */ + public Object remove(int posn) throws InvalidNameException + { + if ( rdns.size() == 0 ) + { + return EMPTY_LDAPDN; + } + + if ( ( posn < 0 ) || ( posn >= rdns.size() ) ) + { + throw new ArrayIndexOutOfBoundsException("The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]"); + } + + int realPos = size() - posn - 1; + LdapRDN rdn = (LdapRDN)rdns.remove( realPos ); + normalize(); + + return rdn; + } + + /** + * Generates a new copy of this name. + * Subsequent changes to the components of this name will not + * affect the new copy, and vice versa. + * + * @return a copy of this name + * + * @see Object#clone() + */ + public Object clone() + { + try + { + LdapDN dn = (LdapDN)super.clone(); + + for ( int i = 0; i < rdns.size(); i++ ) + { + dn.rdns.set( i, ((LdapRDN)rdns.get( i ) ).clone() ); + } + + return dn; + } + catch ( CloneNotSupportedException cnse ) + { + throw new Error( "Assertion failure" ); + } + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) + { + if ( obj instanceof String ) + { + return toString().equals( obj ) ; + } + else if ( obj instanceof LdapDN ) + { + LdapDN name = ( LdapDN ) obj ; + + if ( name.size() != this.size() ) + { + return false ; + } + + for ( int i = 0; i < size(); i++ ) + { + if ( ( (LdapRDN)name.rdns.get( i ) ).compareTo( rdns.get( i ) ) == LdapRDN.NOT_EQUALS) + { + return false; + } + } + + // All components matched so we return true + return true ; + } + else + { + return false ; + } + } + + /** + * Compares this name with another name for order. + * Returns a negative integer, zero, or a positive integer as this + * name is less than, equal to, or greater than the given name. + * + *

As with Object.equals(), the notion of ordering for names + * depends on the class that implements this interface. + * For example, the ordering may be + * based on lexicographical ordering of the name components. + * Specific attributes of the name, such as how it treats case, + * may affect the ordering. In general, two names of different + * classes may not be compared. + * + * @param obj the non-null object to compare against. + * @return a negative integer, zero, or a positive integer as this name + * is less than, equal to, or greater than the given name + * @throws ClassCastException if obj is not a Name of a + * type that may be compared with this name + * + * @see Comparable#compareTo(Object) + */ + public int compareTo(Object obj) + { + if ( obj instanceof LdapDN ) + { + LdapDN ldapDN = (LdapDN)obj; + + if ( ldapDN.size() != size() ) + { + return NOT_EQUALS; + } + + Iterator dn1Iter = rdns.iterator(); + Iterator dn2Iter = ldapDN.rdns.iterator(); + + while ( dn1Iter.hasNext() && dn2Iter.hasNext() ) + { + LdapRDN rdn1 = (LdapRDN)dn1Iter.next(); + LdapRDN rdn2 = (LdapRDN)dn2Iter.next(); + + if ( rdn1.compareTo( rdn2 ) == LdapRDN.NOT_EQUALS ) + { + return NOT_EQUALS; + } + } + + return EQUALS; + } + else + { + return NOT_EQUALS; + } } }