001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.shared.ldap.name;
021    
022    
023    import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
024    
025    
026    /**
027     * This class parse the name-component part or the following BNF grammar (as of
028     * RFC2253, par. 3, and RFC1779, fig. 1) : <br> - &lt;name-component&gt; ::=
029     * &lt;attributeType&gt; &lt;spaces&gt; '=' &lt;spaces&gt;
030     * &lt;attributeValue&gt; &lt;attributeTypeAndValues&gt; <br> -
031     * &lt;attributeTypeAndValues&gt; ::= &lt;spaces&gt; '+' &lt;spaces&gt;
032     * &lt;attributeType&gt; &lt;spaces&gt; '=' &lt;spaces&gt;
033     * &lt;attributeValue&gt; &lt;attributeTypeAndValues&gt; | e <br> -
034     * &lt;attributeType&gt; ::= [a-zA-Z] &lt;keychars&gt; | &lt;oidPrefix&gt; [0-9]
035     * &lt;digits&gt; &lt;oids&gt; | [0-9] &lt;digits&gt; &lt;oids&gt; <br> -
036     * &lt;keychars&gt; ::= [a-zA-Z] &lt;keychars&gt; | [0-9] &lt;keychars&gt; | '-'
037     * &lt;keychars&gt; | e <br> - &lt;oidPrefix&gt; ::= 'OID.' | 'oid.' | e <br> -
038     * &lt;oids&gt; ::= '.' [0-9] &lt;digits&gt; &lt;oids&gt; | e <br> -
039     * &lt;attributeValue&gt; ::= &lt;pairs-or-strings&gt; | '#' &lt;hexstring&gt;
040     * |'"' &lt;quotechar-or-pairs&gt; '"' <br> - &lt;pairs-or-strings&gt; ::= '\'
041     * &lt;pairchar&gt; &lt;pairs-or-strings&gt; | &lt;stringchar&gt;
042     * &lt;pairs-or-strings&gt; | e <br> - &lt;quotechar-or-pairs&gt; ::=
043     * &lt;quotechar&gt; &lt;quotechar-or-pairs&gt; | '\' &lt;pairchar&gt;
044     * &lt;quotechar-or-pairs&gt; | e <br> - &lt;pairchar&gt; ::= ',' | '=' | '+' |
045     * '&lt;' | '&gt;' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F] <br> -
046     * &lt;hexstring&gt; ::= [0-9a-fA-F] [0-9a-fA-F] &lt;hexpairs&gt; <br> -
047     * &lt;hexpairs&gt; ::= [0-9a-fA-F] [0-9a-fA-F] &lt;hexpairs&gt; | e <br> -
048     * &lt;digits&gt; ::= [0-9] &lt;digits&gt; | e <br> - &lt;stringchar&gt; ::=
049     * [0x00-0xFF] - [,=+&lt;&gt;#;\"\n\r] <br> - &lt;quotechar&gt; ::= [0x00-0xFF] -
050     * [\"] <br> - &lt;separator&gt; ::= ',' | ';' <br> - &lt;spaces&gt; ::= ' '
051     * &lt;spaces&gt; | e <br>
052     * <br>
053     * A RDN is a part of a DN. It can be composed of many types, as in the RDN
054     * following RDN :<br>
055     * ou=value + cn=other value<br>
056     * <br>
057     * In this case, we have to store an 'ou' and a 'cn' in the RDN.<br>
058     * <br>
059     * The types are case insensitive. <br>
060     * Spaces before and after types and values are not stored.<br>
061     * Spaces before and after '+' are not stored.<br>
062     * <br>
063     * Thus, we can consider that the following RDNs are equals :<br>
064     * <br>
065     * 'ou=test 1'<br> ' ou=test 1'<br>
066     * 'ou =test 1'<br>
067     * 'ou= test 1'<br>
068     * 'ou=test 1 '<br> ' ou = test 1 '<br>
069     * <br>
070     * So are the following :<br>
071     * <br>
072     * 'ou=test 1+cn=test 2'<br>
073     * 'ou = test 1 + cn = test 2'<br> ' ou =test 1+ cn =test 2 ' <br>
074     * 'cn = test 2 +ou = test 1'<br>
075     * <br>
076     * but the following are not equal :<br>
077     * 'ou=test 1' <br>
078     * 'ou=test 1'<br>
079     * because we have more than one spaces inside the value.<br>
080     * <br>
081     *
082     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
083     * @version $Rev: 923448 $, $Date: 2010-03-15 22:33:42 +0100 (Mon, 15 Mar 2010) $
084     */
085    public class RdnParser
086    {
087        /**
088         * Parse a NameComponent : <br>
089         * <p>
090         * &lt;name-component&gt; ::= &lt;attributeType&gt; &lt;spaces&gt; '='
091         * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
092         * </p>
093         *
094         * @param dn The String to parse
095         * @param rdn The RDN to fill. Beware that if the RDN is not empty, the new
096         *            AttributeTypeAndValue will be added.
097         * @throws LdapInvalidDnException If the NameComponent is invalid
098         */
099        public static void parse( String dn, RDN rdn ) throws LdapInvalidDnException
100        {
101            try
102            {
103                FastDnParser.INSTANCE.parseRdn( dn, rdn );
104            }
105            catch ( TooComplexException e )
106            {
107                rdn.clear();
108                new ComplexDnParser().parseRdn( dn, rdn );
109            }
110        }
111    
112    
113        /**
114         * Validate a NameComponent : <br>
115         * <p>
116         * &lt;name-component&gt; ::= &lt;attributeType&gt; &lt;spaces&gt; '='
117         * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
118         * </p>
119         *
120         * @param dn The string to parse
121         * @return <code>true</code> if the RDN is valid
122         */
123        public static boolean isValid( String dn )
124        {
125            RDN rdn = new RDN();
126            try
127            {
128                parse( dn, rdn );
129                return true;
130            }
131            catch ( LdapInvalidDnException e )
132            {
133                return false;
134            }
135        }
136    
137    }