Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 30051 invoked from network); 3 Jul 2005 14:20:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 3 Jul 2005 14:20:14 -0000 Received: (qmail 47708 invoked by uid 500); 3 Jul 2005 14:20:13 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 47673 invoked by uid 500); 3 Jul 2005 14:20:12 -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 47660 invoked by uid 99); 3 Jul 2005 14:20:12 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 03 Jul 2005 07:20:12 -0700 X-ASF-Spam-Status: No, hits=0.2 required=10.0 tests=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, 03 Jul 2005 07:20:13 -0700 Received: (qmail 30009 invoked by uid 65534); 3 Jul 2005 14:20:09 -0000 Message-ID: <20050703142009.30008.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r208918 - /directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java Date: Sun, 03 Jul 2005 14:20:09 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.2 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 Jul 3 07:20:08 2005 New Revision: 208918 URL: http://svn.apache.org/viewcvs?rev=208918&view=rev Log: Added the RelativeLdapDN class. Added: directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java Added: directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java?rev=208918&view=auto ============================================================================== --- directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java (added) +++ directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/primitives/RelativeLdapDN.java Sun Jul 3 07:20:08 2005 @@ -0,0 +1,496 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.asn1.ldap.codec.primitives; + +import org.apache.asn1.DecoderException; +import org.apache.asn1.ldap.codec.utils.DNUtils; +import org.apache.asn1.util.MutableString; +import org.apache.asn1.util.StringUtils; + + +/** + * This class parses a relative LDdapDN, which is a name-component + * of the LdapDN grammar + * + * The relative DN MUST respect this BNF grammar (a subset of the RFC2253, par. 3, and RFC1779, fig. 1)
+ * + *

+ *- <name-component> ::= <attributeType> <spaces> '=' <spaces> <attributeValue> <attributeTypeAndValues>
+ *- <attributeTypeAndValues> ::= <spaces> '+' <spaces> <attributeType> <spaces> '=' <spaces> <attributeValue> <attributeTypeAndValues> | e
+ *- <attributeType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9] <digits> <oids> | [0-9] <digits> <oids>
+ *- <keychars> ::= [a-zA-Z] <keychars> | [0-9] <keychars> | '-' <keychars> | e
+ *- <oidPrefix> ::= 'OID.' | 'oid.' | e
+ *- <oids> ::= '.' [0-9] <digits> <oids> | e
+ *- <attributeValue> ::= <pairs-or-strings> | '#' <hexstring> |'"' <quotechar-or-pairs> '"'
+ *- <pairs-or-strings> ::= '\' <pairchar> <pairs-or-strings> | <stringchar> <pairs-or-strings> | e
+ *- <quotechar-or-pairs> ::= <quotechar> <quotechar-or-pairs> | '\' <pairchar> <quotechar-or-pairs> | e
+ *- <pairchar> ::= ',' | '=' | '+' | '<' | '>' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F]
+ *- <hexstring> ::= [0-9a-fA-F] [0-9a-fA-F] <hexpairs>
+ *- <hexpairs> ::= [0-9a-fA-F] [0-9a-fA-F] <hexpairs> | e
+ *- <digits> ::= [0-9] <digits> | e
+ *- <stringchar> ::= [0x00-0xFF] - [,=+<>#;\"\n\r]
+ *- <quotechar> ::= [0x00-0xFF] - [\"]
+ *- <spaces> ::= ' ' <spaces> | e
+ *

+ * + * @author Apache Directory Project + */ +public class RelativeLdapDN extends MutableString +{ + //~ Static fields/initializers ----------------------------------------------------------------- + + /** "oid." static */ + private static final byte[] OID_LOWER = new byte[] { 'o', 'i', 'd', '.' }; + + /** "OID." static */ + private static final byte[] OID_UPPER = new byte[] { 'O', 'I', 'D', '.' }; + + /** A null LdapDN */ + public transient static final RelativeLdapDN EMPTY_STRING = new RelativeLdapDN(); + + //~ Methods ------------------------------------------------------------------------------------ + + /** + * Walk the buffer while the current char is a Space char + *

+ * <spaces> ::= ' ' <spaces> | e + *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer + */ + protected static int parseSpaces( byte[] bytes, int pos ) + { + + while ( StringUtils.isCharASCII( bytes, pos, ' ' ) ) + { + pos++; + } + + return pos; + } + + /** + * Parse this rule :
+ *

+ * <attributeValue> ::= <pairs-or-strings> | '#' <hexstring> |'"' <quotechar-or-pairs> '"'
+ * <pairs-or-strings> ::= '\' <pairchar> <pairs-or-strings> | <stringchar> <pairs-or-strings> | | e
+ * <quotechar-or-pairs> ::= <quotechar> <quotechar-or-pairs> | '\' <pairchar> <quotechar-or-pairs> | e
+ *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseAttributeValue( byte[] bytes, int pos ) + { + if ( StringUtils.isCharASCII( bytes, pos, '#' ) ) + { + pos++; + + // ::= '#' + if ( ( pos = DNUtils.parseHexString( bytes, pos ) ) == -1 ) + { + + return -1; + } + + return parseSpaces( bytes, pos ); + } + else if ( StringUtils.isCharASCII( bytes, pos, '"' ) ) + { + pos++; + int nbBytes = 0; + + // ::= '"' '"' + // ::= | '\' | e + while ( true ) + { + if ( StringUtils.isCharASCII( bytes, pos, '\\' ) ) + { + pos++; + + if ( DNUtils.isPairChar( bytes, pos ) ) + { + pos++; + } + else + { + return -1; + } + } + else if ( (nbBytes = DNUtils.isQuoteChar( bytes, pos ) ) != -1 ) + { + pos += nbBytes; + } + else + { + break; + } + } + + if ( StringUtils.isCharASCII( bytes, pos, '"' ) ) + { + pos++; + + return parseSpaces( bytes, pos ); + } + else + { + return -1; + } + } + else + { + while ( true ) + { + if ( StringUtils.isCharASCII( bytes, pos, '\\' ) ) + { + // '\' + pos++; + + if ( DNUtils.isPairChar( bytes, pos ) == false ) + { + return -1; + } + else + { + pos++; + } + } + else + { + int nbBytes = 0; + + // + if ( (nbBytes = DNUtils.isStringChar( bytes, pos )) != -1) + { + // A special case : if we have some spaces before the '+' character, + // we MUST skip them. + int initPos = pos; + + if ( StringUtils.isCharASCII( bytes, pos, ' ') ) + { + pos = parseSpaces( bytes, pos ); + + if ( ( DNUtils.isStringChar( bytes, pos ) == -1 ) && + ( StringUtils.isCharASCII( bytes, pos, '\\' ) == false ) ) + { + // Ok, we are done with the stringchar. + return pos; + } + } + else + { + // An unicode char could be more than one byte long + pos += nbBytes; + } + } + else + { + return pos; + } + } + } + } + } + + /** + * Parse this rule :
+ *

+ * <oidPrefix> ::= 'OID.' | 'oid.' | e + *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseOidPrefix( byte[] bytes, int pos ) + { + + if ( ( StringUtils.areEquals( bytes, pos, OID_LOWER ) == -1 ) && + ( StringUtils.areEquals( bytes, pos, OID_UPPER ) == -1 ) ) + { + + return -1; + } + else + { + pos += 4; + + return pos; + } + } + + /** + * Parse this rule :
+ *

+ * <oidValue> ::= [0-9] <digits> <oids> + *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseOidValue(byte[] bytes, int pos) + { + // ::= [0-9] + if ( StringUtils.isDigit( bytes, pos ) == false ) + { + + // Nope... An error + return -1; + } + else + { + + // Let's process an oid + pos++; + + while ( StringUtils.isDigit( bytes, pos ) ) + { + pos++; + } + + // ::= '.' [0-9] | e + if ( StringUtils.isCharASCII( bytes, pos, '.' ) == false ) + { + + return pos; + } + else + { + + do + { + pos++; + + if ( StringUtils.isDigit( bytes, pos ) == false ) + { + + return -1; + } + else + { + pos++; + + while ( StringUtils.isDigit( bytes, pos ) ) + { + pos++; + } + } + } + while ( StringUtils.isCharASCII( bytes, pos, '.' ) ); + + return pos; + } + } + } + + /** + * Parse this rule :
+ *

+ * <attributType> ::= [a-zA-Z] <keychars> | + * <oidPrefix> [0-9] <digits> <oids> | [0-9] <digits> <oids> + *

+ * + * The string *MUST* be an ASCII string, not an unicode string. + * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseAttributeType( byte[] bytes, int pos ) + { + + // ::= [a-zA-Z] | [0-9] | [0-9] + + if ( StringUtils.isAlphaASCII( bytes, pos )) + { + // ::= [a-zA-Z] | [0-9] + + // We have got an Alpha char, it may be the begining of an OID ? + int oldPos = pos; + + if ( ( pos = parseOidPrefix( bytes, oldPos ) ) != -1 ) + { + return parseOidValue(bytes, pos); + } + else + { + // It's not an oid, it's a String (ASCII) + // ::= [a-zA-Z] + // ::= [a-zA-Z] | [0-9] | '-' | e + pos = oldPos + 1; + + while ( StringUtils.isAlphaDigitMinus( bytes, pos ) ) + { + pos++; + } + + return pos; + } + } + else + { + + // An oid + // ::= [0-9] + return parseOidValue(bytes, pos); + } + } + + /** + * Parse this rule :
+ *

+ * <attributeTypeAndValues> ::= <spaces> '+' <spaces> <attributeType> <spaces> '=' <spaces> <attributeValue> <attributeTypeAndValues> | e + *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the byte buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseAttributeTypeAndValues( byte[] bytes, int pos ) + { + + while ( true ) + { + pos = parseSpaces( bytes, pos ); + + if ( StringUtils.isCharASCII( bytes, pos, '+' ) ) + { + pos++; + } + else + { + + // ::= e + return pos; + } + + pos = parseSpaces( bytes, pos ); + + if ( ( pos = parseAttributeType( bytes, pos ) ) == -1 ) + { + + return -1; + } + + pos = parseSpaces( bytes, pos ); + + if ( StringUtils.isCharASCII( bytes, pos, '=' ) ) + { + pos++; + } + else + { + + return -1; + } + + pos = parseSpaces( bytes, pos ); + + return parseAttributeValue( bytes, pos ); + } + } + + /** + * Parse this rule :
+ *

+ * <name-component> ::= <attributeType> <spaces> '=' <spaces> <attributeValue> <attributeTypeAndValues> + *

+ * + * @param bytes The buffer to parse + * @param pos The current position in the buffer + * @return The new position in the byte buffer, or -1 if the rule does not apply to the byte buffer + */ + protected static int parseNameComponent( byte[] bytes, int pos ) + { + + if ( ( pos = parseAttributeType( bytes, pos ) ) == -1 ) + { + + return -1; + } + + pos = parseSpaces( bytes, pos ); + + if ( StringUtils.isCharASCII( bytes, pos, '=' ) == false ) + { + + return -1; + } + else + { + pos++; + } + + pos = parseSpaces( bytes, pos ); + + if ( ( pos = parseAttributeValue( bytes, pos ) ) == -1 ) + { + + return -1; + } + + return parseAttributeTypeAndValues( bytes, pos ); + } + + /** + * Construct an empty LdapDN object + */ + protected RelativeLdapDN(int length, boolean isStreamed) + { + super(length, isStreamed); + } + + /** + * Construct an empty LdapDN object + */ + protected RelativeLdapDN() + { + super(0, false); + } + + /** + * Parse a buffer and checks that it is a valid relative DN
+ * + * @param bytes The byte buffer that contains the relative DN + * @exception A DecoderException is thrown if the buffer does not contains a valid relative DN. + */ + protected RelativeLdapDN( byte[] bytes ) throws DecoderException + { + + if ( bytes == null || bytes.length == 0) + { + return; + } + + int pos = 0; + + // Parse the name component + if ( ( pos = parseNameComponent( bytes, pos ) ) == -1 ) + { + throw new DecoderException( "Bad relative DN : " + new String( bytes) ); + } + + int stringLength = StringUtils.countChars(bytes); + + setData(bytes); + } +}