You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2006/12/14 16:38:35 UTC

svn commit: r487240 - in /directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name: LdapDN.java LdapDnParser.java Rdn.java RdnParser.java

Author: elecharny
Date: Thu Dec 14 07:38:34 2006
New Revision: 487240

URL: http://svn.apache.org/viewvc?view=rev&rev=487240
Log:
Added an isvalid() method in LdapDN to allow the SyntaxChecker to validate a DN without
building the object.
Fixed some warnings

Modified:
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java?view=diff&rev=487240&r1=487239&r2=487240
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java Thu Dec 14 07:38:34 2006
@@ -61,7 +61,7 @@
 public class LdapDN /* extends LdapString */implements Name
 {
    /** The LoggerFactory used by this class */
-   private static Logger log = LoggerFactory.getLogger( LdapDN.class );
+   protected static Logger log = LoggerFactory.getLogger( LdapDN.class );
 
    /**
     * Declares the Serial Version Uid.
@@ -81,7 +81,7 @@
    // ~ Static fields/initializers
    // -----------------------------------------------------------------
    /** The RDNs that are elements of the DN */
-   private List<Rdn> rdns = new ArrayList<Rdn>( 5 );
+   protected List<Rdn> rdns = new ArrayList<Rdn>( 5 );
 
    /** The user provided name */
    private String upName;
@@ -120,7 +120,7 @@
        {
            for ( int ii = 0; ii < name.size(); ii++ )
            {
-               String nameComponent = ( String ) name.get( ii );
+               String nameComponent = name.get( ii );
                add( nameComponent );
            }
        }
@@ -524,7 +524,11 @@
     */
    public boolean startsWith( Name name )
    {
-       if ( name instanceof LdapDN )
+       if ( name == null )
+       {
+           return true;
+       }
+       else if ( name instanceof LdapDN )
        {
            LdapDN nameDN = ( LdapDN ) name;
 
@@ -555,7 +559,7 @@
 
            return true;
        }
-       else if ( name instanceof Name )
+       else
        {
            if ( name.size() == 0 )
            {
@@ -578,7 +582,7 @@
                
                try
                {
-                   nameRdn = new Rdn( ( String ) name.get( name.size() - i - 1 ) );
+                   nameRdn = new Rdn( name.get( name.size() - i - 1 ) );
                }
                catch ( InvalidNameException e )
                {
@@ -594,11 +598,6 @@
 
            return true;
        }
-       else
-       {
-           // We don't accept a Name which is not a LdapName
-           return name == null;
-       }
    }
 
 
@@ -738,7 +737,7 @@
     *
     * @return All the components
     */
-   public List getRdns()
+   public List<Rdn> getRdns()
    {
        List<Rdn> newRdns = new ArrayList<Rdn>();
 
@@ -1028,7 +1027,7 @@
     *             if adding <tt>RDN</tt> would violate the syntax rules of
     *             this name
     */
-   public Name add( Rdn newRdn ) throws InvalidNameException
+   public Name add( Rdn newRdn )
    {
        rdns.add( 0, newRdn );
        normalizeInternal();
@@ -1255,7 +1254,7 @@
 
                if ( oidNormalizer != null )
                {
-                   return new AttributeTypeAndValue( oidNormalizer.getAttributeTypeOid(), ( String ) oidNormalizer.getNormalizer()
+                   return new AttributeTypeAndValue( oidNormalizer.getAttributeTypeOid(), oidNormalizer.getNormalizer()
                        .normalize( atav.getValue() ) );
 
                }
@@ -1335,7 +1334,7 @@
                        value = DefaultStringNormalizer.normalizeString( ( String ) value );
 
                        rdn.addAttributeTypeAndValue( oidNormalizer.getAttributeTypeOid(),
-                           ( String ) oidNormalizer.getNormalizer()
+                           oidNormalizer.getNormalizer()
                            .normalize( value ) );
 
                    }
@@ -1423,18 +1422,30 @@
            return;
        }
 
-       Enumeration<Rdn> rdns = getAllRdn();
+       Enumeration<Rdn> localRdns = getAllRdn();
 
        // Loop on all RDNs
-       while ( rdns.hasMoreElements() )
+       while ( localRdns.hasMoreElements() )
        {
-           Rdn rdn = rdns.nextElement();
-           String upName = rdn.getUpName();
+           Rdn rdn = localRdns.nextElement();
+           String localUpName = rdn.getUpName();
            rdnOidToName( rdn, oidsMap );
            rdn.normalize();
-           rdn.setUpName( upName );
+           rdn.setUpName( localUpName );
        }
 
        normalizeInternal();
+   }
+   
+   /**
+    * Check if a DistinguishedName is syntaxically valid
+    *
+    * @param dn The DN to validate
+    * @return <code>true></code> if the DN is valid, <code>false</code>
+    * otherwise
+    */
+   public static boolean isValid( String dn )
+   {
+       return LdapDnParser.validateInternal( dn );
    }
 }

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java?view=diff&rev=487240&r1=487239&r2=487240
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java Thu Dec 14 07:38:34 2006
@@ -77,6 +77,7 @@
     */
    private LdapDnParser()
    {
+       // Nothing to do
    }
 
 
@@ -146,6 +147,60 @@
        else
        {
            throw new InvalidNameException( "Bad DN : " + dn );
+       }
+   }
+
+
+   /**
+    * Validate a DN
+    *
+    * @param dn
+    *            The DN to be parsed
+    *            
+    * @return <code>true</code> if the DN is valid
+    */
+   public static boolean validateInternal( String dn )
+   {
+       if ( dn.length() == 0 )
+       {
+           // We have an empty DN, just get out of the function.
+           return true;
+       }
+
+       Position pos = new Position();
+       pos.start = 0;
+
+       // <name> ::= <name-component> <name-components>
+       // <name-components> ::= <spaces> <separator> <spaces> <name-component>
+       // <name-components> | e
+       if ( RdnParser.isValid( dn, pos, true ) )
+       {
+           // Now, parse the following nameComponents
+           do
+           {
+               if ( ( StringTools.isCharASCII( dn, pos.start, ',' ) == false )
+                   && ( StringTools.isCharASCII( dn, pos.start, ';' ) == false ) )
+               {
+
+                   if ( pos.start != dn.length() )
+                   {
+                       return false;
+                   }
+                   else
+                   {
+                       break;
+                   }
+               }
+
+               pos.start++;
+           }
+           while ( RdnParser.isValid( dn, pos, false ) );
+           
+           return true;
+       }
+       else
+       {
+           return false;
        }
    }
 

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java?view=diff&rev=487240&r1=487239&r2=487240
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java Thu Dec 14 07:38:34 2006
@@ -152,7 +152,7 @@
     * case where we only have a single type=value. This will be 99.99% the
     * case. This avoids the creation of a HashMap.
     */
-   private AttributeTypeAndValue atav = null;
+   protected AttributeTypeAndValue atav = null;
 
    /**
     * The number of atavs. We store this number here to avoid complex
@@ -277,7 +277,7 @@
 
                while ( iter.hasNext() )
                {
-                   AttributeTypeAndValue currentAtav = ( AttributeTypeAndValue ) iter.next();
+                   AttributeTypeAndValue currentAtav = iter.next();
                    atavs.add( (AttributeTypeAndValue)currentAtav.clone() );
                    atavTypes.put( currentAtav.getType(), currentAtav );
                }
@@ -522,7 +522,7 @@
            default:
                if ( atavTypes.containsKey( normalizedType ) )
                {
-                   return ( AttributeTypeAndValue ) atavTypes.get( normalizedType );
+                   return atavTypes.get( normalizedType );
                }
                else
                {
@@ -564,7 +564,7 @@
 
                public void remove()
                {
-
+                   // nothing to do
                }
            };
        }
@@ -855,7 +855,7 @@
            return false;
        }
 
-       return compareTo( ( Rdn ) rdn ) == EQUALS;
+       return compareTo( rdn ) == EQUALS;
    }
 
 
@@ -1021,7 +1021,7 @@
                    {
                        if ( StringTools.isHex( chars, i ) )
                        {
-                           pair += ( byte ) StringTools.HEX_VALUE[chars[i]];
+                           pair += StringTools.HEX_VALUE[chars[i]];
                            bytes[pos++] = pair;
                        }
                    }

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java?view=diff&rev=487240&r1=487239&r2=487240
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java Thu Dec 14 07:38:34 2006
@@ -156,6 +156,71 @@
         }
     }
 
+    /**
+     * Validate this rule : <br>
+     * <p>
+     * &lt;oidValue&gt; ::= [0-9] &lt;digits&gt; &lt;oids&gt;
+     * </p>
+     *
+     * @param chars
+     *            The char array to parse
+     * @param pos
+     *            The current position in the byte buffer
+     * @return <code>true</code> if this is a valid OID
+     */
+    private static boolean isValidOidValue( String string, Position pos )
+    {
+        pos.start += pos.length;
+        pos.end = pos.start;
+
+        // <attributType> ::= [0-9] <digits> <oids>
+        if ( StringTools.isDigit( string, pos.start ) == false )
+        {
+            // Nope... An error
+            return false;
+        }
+        else
+        {
+            // Let's process an oid
+            pos.end++;
+
+            while ( StringTools.isDigit( string, pos.end ) )
+            {
+                pos.end++;
+            }
+
+            // <oids> ::= '.' [0-9] <digits> <oids> | e
+            if ( StringTools.isCharASCII( string, pos.end, '.' ) == false )
+            {
+                return false;
+            }
+            else
+            {
+                do
+                {
+                    pos.end++;
+
+                    if ( StringTools.isDigit( string, pos.end ) == false )
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        pos.end++;
+
+                        while ( StringTools.isDigit( string, pos.end ) )
+                        {
+                            pos.end++;
+                        }
+                    }
+
+                }
+                while ( StringTools.isCharASCII( string, pos.end, '.' ) );
+
+                return true;
+            }
+        }
+    }
 
     /**
      * Parse this rule : <br>
@@ -241,6 +306,61 @@
         }
     }
 
+    /**
+     * Parse this rule : <br>
+     * <p>
+     * &lt;attributType&gt; ::= [a-zA-Z] &lt;keychars&gt; | &lt;oidPrefix&gt;
+     * [0-9] &lt;digits&gt; &lt;oids&gt; | [0-9] &lt;digits&gt; &lt;oids&gt;
+     * </p>
+     * The string *MUST* be an ASCII string, not an unicode string.
+     *
+     * @param chars
+     *            The char array to parse
+     * @param pos
+     *            The current position in the char array
+     * @return The new position in the char array, or PARSING_ERROR if the rule
+     *         does not apply to the char array
+     */
+    private static boolean isValidAttributeType( String string, Position pos )
+    {
+        // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9] <digits>
+        // <oids> | [0-9] <digits> <oids>
+        if ( StringTools.isAlphaASCII( string, pos.start ) )
+        {
+            // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9]
+            // <digits> <oids>
+
+            // We have got an Alpha char, it may be the begining of an OID ?
+            if ( parseOidPrefix( string, pos ) != DNUtils.PARSING_ERROR )
+            {
+                pos.length = 4;
+
+                return isValidOidValue( string, pos );
+            }
+            else
+            {
+                // It's not an oid, it's a String (ASCII)
+                // <attributType> ::= [a-zA-Z] <keychars>
+                // <keychars> ::= [a-zA-Z] <keychar> | [0-9] <keychar> | '-'
+                // <keychar> | e
+                pos.end++;
+
+                while ( StringTools.isAlphaDigitMinus( string, pos.end ) )
+                {
+                    pos.end++;
+                }
+
+                return true;
+            }
+        }
+        else
+        {
+            // An oid
+            // <attributType> ::= [0-9] <digits> <oids>
+            return isValidOidValue( string, pos );
+        }
+    }
+
 
     /**
      * Parse this rule : <br>
@@ -448,6 +568,163 @@
         }
     }
 
+    /**
+     * Validate this rule : <br>
+     * <p>
+     * &lt;attributeValue&gt; ::= &lt;pairs-or-strings&gt; | '#'
+     *     &lt;hexstring&gt; |'"' &lt;quotechar-or-pairs&gt; '"' <br>
+     * &lt;pairs-or-strings&gt; ::= '\' &lt;pairchar&gt;
+     * &lt;pairs-or-strings&gt; | &lt;stringchar&gt; &lt;pairs-or-strings&gt; | |
+     * e <br>
+     * &lt;quotechar-or-pairs&gt; ::= &lt;quotechar&gt;
+     * &lt;quotechar-or-pairs&gt; | '\' &lt;pairchar&gt;
+     * &lt;quotechar-or-pairs&gt; | e <br>
+     * </p>
+     *
+     * @param chars
+     *            The char array to parse
+     * @param pos
+     *            The current position in the char array
+     * @return <code>true</code> if the rule is valid
+     */
+    private static boolean isValidAttributeValue( String string, Position pos )
+    {
+        char c = StringTools.charAt( string, pos.start );
+
+        if ( c == '#' )
+        {
+            pos.start++;
+            int nbHex = 0;
+            int currentPos = pos.start;
+
+            // First, we will count the number of hexPairs
+            while ( DNUtils.parseHexPair( string, currentPos ) >= 0 )
+            {
+                nbHex++;
+                currentPos += DNUtils.TWO_CHARS;
+            }
+
+            byte[] hexValue = new byte[nbHex];
+
+            // Now, convert the value
+            // <attributeValue> ::= '#' <hexstring>
+            if ( DNUtils.parseHexString( string, hexValue, pos ) == DNUtils.PARSING_ERROR )
+            {
+                return false;
+            }
+
+            pos.start--;
+            StringTools.trimRight( string, pos );
+            pos.length = pos.end - pos.start;
+
+            return true;
+        }
+        else if ( c == '"' )
+        {
+            pos.start++;
+            pos.length = 0;
+            pos.end = pos.start;
+            int nbBytes = 0;
+
+            // <attributeValue> ::= '"' <quotechar-or-pair> '"'
+            // <quotechar-or-pairs> ::= <quotechar> <quotechar-or-pairs> | '\'
+            //                                                  <pairchar> <quotechar-or-pairs> | e
+            while ( true )
+            {
+                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                {
+                    pos.end++;
+                    int nbChars = 0;
+
+                    if ( ( nbChars = DNUtils.isPairChar( string, pos.start ) ) != DNUtils.PARSING_ERROR )
+                    {
+                        pos.end += nbChars;
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                else if ( ( nbBytes = DNUtils.isQuoteChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                {
+                    pos.end += nbBytes;
+                }
+                else
+                {
+                    pos.length = pos.end - pos.start;
+                    break;
+                }
+            }
+
+            if ( StringTools.isCharASCII( string, pos.end, '"' ) )
+            {
+                pos.end++;
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else
+        {
+            while ( true )
+            {
+                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                {
+                    // '\' <pairchar> <pairs-or-strings>
+                    pos.end++;
+
+                    int nbChars = 0;
+                    
+                    if ( ( nbChars = DNUtils.isPairChar( string, pos.end ) ) == DNUtils.PARSING_ERROR )
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        pos.end += nbChars;
+                    }
+                }
+                else
+                {
+                    int nbChars = 0;
+
+                    // <stringchar> <pairs-or-strings>
+                    if ( ( nbChars = DNUtils.isStringChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                    {
+                        // A special case : if we have some spaces before the
+                        // '+' character,
+                        // we MUST skip them.
+                        if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+                        {
+                            //StringTools.trimLeft( string, pos );
+
+                            if ( ( DNUtils.isStringChar( string, pos.end ) == DNUtils.PARSING_ERROR )
+                                && ( StringTools.isCharASCII( string, pos.end, '\\' ) == false ) )
+                            {
+                                // Ok, we are done with the stringchar.
+                                return true;
+                            }
+                            else
+                            {
+                                pos.end++;
+                            }
+                        }
+                        else
+                        {
+                            pos.end += nbChars;
+                        }
+                    }
+                    else
+                    {
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+
 
     /**
      * Parse this rule : <br>
@@ -526,6 +803,71 @@
 
 
     /**
+     * Validate this rule : <br>
+     * <p>
+     * &lt;nameComponents&gt; ::= &lt;spaces&gt; '+' &lt;spaces&gt;
+     * &lt;attributeType&gt; &lt;spaces&gt; '=' &lt;spaces&gt;
+     * &lt;attributeValue&gt; &lt;nameComponents&gt; | e
+     * </p>
+     *
+     * @param chars
+     *            The char buffer to parse
+     * @param pos
+     *            The current position in the byte buffer
+     * @return <code>true</code> if the rule is valid
+     */
+    private static boolean isValidNameComponents( String string, Position pos, boolean isFirstRdn )
+    {
+        int newStart = 0;
+
+        while ( true )
+        {
+            StringTools.trimLeft( string, pos );
+
+            if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+            {
+                pos.start++;
+            }
+            else
+            {
+                // <attributeTypeAndValues> ::= e
+                return true;
+            }
+
+            StringTools.trimLeft( string, pos );
+
+            if ( !isValidAttributeType( string, pos ) )
+            {
+                return false;
+            }
+
+            pos.start = pos.end;
+
+            StringTools.trimLeft( string, pos );
+
+            if ( StringTools.isCharASCII( string, pos.end, '=' ) )
+            {
+                pos.start++;
+            }
+            else
+            {
+                return false;
+            }
+
+            StringTools.trimLeft( string, pos );
+
+            if ( !isValidAttributeValue( string, pos ) )
+            {
+                return false;
+            }
+
+            newStart = pos.end;
+            pos.start = newStart;
+            pos.end = newStart;
+        }
+    }
+
+    /**
      * Unescape pairChars.
      * 
      * A PairChar can be a char if it's 
@@ -629,6 +971,62 @@
         return DNUtils.PARSING_OK;
     }
 
+    /**
+     * Validate a NameComponent : <br>
+     * <p>
+     * &lt;name-component&gt; ::= &lt;attributeType&gt; &lt;spaces&gt; '='
+     * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
+     * </p>
+     *
+     * @param dn The String to parse
+     * @param pos The current position in the buffer
+     * @return <code>true</code> if the RDN is valid
+     */
+    public static boolean isValid( String dn, Position pos, boolean isfirstRdn )
+    {
+        StringTools.trimLeft( dn, pos );
+
+        pos.end = pos.start;
+        pos.length = 0;
+        
+        if ( !isValidAttributeType( dn, pos ) )
+        {
+            return false;
+        }
+
+        pos.start = pos.end;
+
+        StringTools.trimLeft( dn, pos );
+
+        if ( StringTools.isCharASCII( dn, pos.start, '=' ) == false )
+        {
+            return false;
+        }
+        else
+        {
+            pos.start++;
+        }
+
+        StringTools.trimLeft( dn, pos );
+
+        pos.end = pos.start;
+
+        if ( !isValidAttributeValue( dn, pos ) )
+        {
+            return false;
+        }
+
+        pos.start = pos.end;
+        pos.length = 0;
+
+        if ( !isValidNameComponents( dn, pos, isfirstRdn )  )
+        {
+            return false;
+        }
+        
+        pos.start = pos.end;
+        return true;
+    }
 
     /**
      * Parse a NameComponent : <br>
@@ -647,5 +1045,24 @@
     {
         parse( string, new Position(), rdn );
         rdn.normalize();
+    }
+
+    /**
+     * Validtae a NameComponent : <br>
+     * <p>
+     * &lt;name-component&gt; ::= &lt;attributeType&gt; &lt;spaces&gt; '='
+     * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
+     * </p>
+     *
+     * @param string
+     *            The buffer to parse
+     * @param rdn
+     *            The RDN to fill. Beware that if the RDN is not empty, the new
+     *            AttributeTypeAndValue will be added.
+     * @return <code>true</code> if the RDN is valid
+     */
+    public static boolean isValid( String string )
+    {
+        return isValid( string, new Position(), false );
     }
 }