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 2023/03/05 04:57:48 UTC
[directory-ldap-api] branch master updated: Fixed a multi-component DN parsing issue: the ordering was not correct
This is an automated email from the ASF dual-hosted git repository.
elecharny pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-ldap-api.git
The following commit(s) were added to refs/heads/master by this push:
new 5df9f63c2 Fixed a multi-component DN parsing issue: the ordering was not correct
5df9f63c2 is described below
commit 5df9f63c22f3af73fb898cb7b9551e513c12b6a1
Author: emmanuel lecharny <el...@apache.org>
AuthorDate: Sun Mar 5 05:57:36 2023 +0100
Fixed a multi-component DN parsing issue: the ordering was not correct
---
.../directory/api/ldap/model/name/DnTest.java | 88 ++++---
.../api/ldap/model/name/FastParserRdnTest.java | 2 +-
.../directory/api/ldap/model/name/RdnTest.java | 10 +-
...stParserRdnTest.java => SchemaAwareDnTest.java} | 85 +++----
ldap/model/src/main/antlr/distinguishedName.g | 252 +++++++++++++--------
.../api/ldap/model/ldif/LdifRevertor.java | 2 +-
.../apache/directory/api/ldap/model/name/Ava.java | 50 +++-
.../apache/directory/api/ldap/model/name/Dn.java | 59 ++++-
.../api/ldap/model/name/FastDnParser.java | 2 +-
.../apache/directory/api/ldap/model/name/Rdn.java | 21 +-
.../api/ldap/model/ldif/LdifRevertorTest.java | 16 +-
.../api/ldap/model/name/DnParserTest.java | 4 +-
12 files changed, 356 insertions(+), 235 deletions(-)
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
index 8b21fe030..984ae2b2b 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/DnTest.java
@@ -2040,13 +2040,11 @@ public class DnTest
Dn result = new Dn( schemaManager, name );
- assertTrue(
- result.equals(
- "0.9.2342.19200300.100.1.25=and some animals+ou=some people,0.9.2342.19200300.100.1.25=eXample,dc=cOm" ) );
- assertTrue( ( result )
- .getName()
- .equals(
- "ou= Some People + 0.9.2342.19200300.100.1.25= And Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm" ) );
+ assertEquals( result,
+ "0.9.2342.19200300.100.1.25=and some animals+ou=some people,0.9.2342.19200300.100.1.25=eXample,dc=cOm" );
+ assertEquals(
+ "ou= Some People + 0.9.2342.19200300.100.1.25= And Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm",
+ result.getName() );
}
@@ -2674,27 +2672,27 @@ public class DnTest
Dn dn = new Dn( " ou = Example + cn = TEST , ou = COM " );
new Dn( schemaManager, dn );
- assertEquals( "ou=Example+cn=TEST,ou=COM", dn.getEscaped() );
+ assertEquals( "cn=TEST+ou=Example,ou=COM", dn.getEscaped() );
assertEquals( " ou = Example + cn = TEST , ou = COM ", dn.getName() );
Rdn rdn = dn.getRdn();
- assertEquals( "ou", rdn.getNormType() );
- assertEquals( "ou=Example+cn=TEST", rdn.getEscaped() );
- assertEquals( "ou", rdn.getType() );
- assertEquals( "Example", rdn.getValue() );
+ assertEquals( "cn", rdn.getNormType() );
+ assertEquals( "cn=TEST+ou=Example", rdn.getEscaped() );
+ assertEquals( "cn", rdn.getType() );
+ assertEquals( "TEST", rdn.getValue() );
assertEquals( " ou = Example + cn = TEST ", rdn.getName() );
// The first ATAV
Ava atav = rdn.getAva();
- assertEquals( "ou=Example", atav.getEscaped() );
- assertEquals( "ou", atav.getNormType() );
- assertEquals( "Example", atav.getValue().getString() );
+ assertEquals( "cn=TEST", atav.getEscaped() );
+ assertEquals( "cn", atav.getNormType() );
+ assertEquals( "TEST", atav.getValue().getString() );
- assertEquals( "ou", atav.getType() );
- assertEquals( "Example", atav.getValue().getString() );
+ assertEquals( "cn", atav.getType() );
+ assertEquals( "TEST", atav.getValue().getString() );
- assertEquals( " ou = Example ", atav.getName() );
+ assertEquals( " cn = TEST ", atav.getName() );
assertEquals( 2, rdn.size() );
@@ -2775,29 +2773,29 @@ public class DnTest
// ------------------------------------------------------------------
// Before normalization
assertEquals( " OU = Ex\\+mple + cn = T\\+ST\\ , ou = COM ", dn.getName() );
- assertEquals( "OU=Ex\\+mple+cn=T\\+ST\\ ,ou=COM", dn.getEscaped() );
+ assertEquals( "cn=T\\+ST\\ +OU=Ex\\+mple,ou=COM", dn.getEscaped() );
// Check the first Rdn
Rdn rdn = dn.getRdn();
assertEquals( " OU = Ex\\+mple + cn = T\\+ST\\ ", rdn.getName() );
- assertEquals( "OU=Ex\\+mple+cn=T\\+ST\\ ", rdn.getEscaped() );
+ assertEquals( "cn=T\\+ST\\ +OU=Ex\\+mple", rdn.getEscaped() );
- assertEquals( "OU", rdn.getType() );
- assertEquals( "ou", rdn.getNormType() );
+ assertEquals( "cn", rdn.getType() );
+ assertEquals( "cn", rdn.getNormType() );
- assertEquals( "Ex+mple", rdn.getValue() );
- assertEquals( "Ex+mple", rdn.getAva().getValue().getString() );
+ assertEquals( "T+ST ", rdn.getValue() );
+ assertEquals( "T+ST ", rdn.getAva().getValue().getString() );
// The first ATAV
Ava atav = rdn.getAva();
- assertEquals( " OU = Ex\\+mple ", atav.getName() );
- assertEquals( "OU=Ex\\+mple", atav.getEscaped() );
+ assertEquals( " cn = T\\+ST\\ ", atav.getName() );
+ assertEquals( "cn=T\\+ST\\ ", atav.getEscaped() );
- assertEquals( "ou", atav.getNormType() );
- assertEquals( "OU", atav.getType() );
+ assertEquals( "cn", atav.getNormType() );
+ assertEquals( "cn", atav.getType() );
- assertEquals( "Ex+mple", atav.getValue().getString() );
+ assertEquals( "T+ST ", atav.getValue().getString() );
assertEquals( 2, rdn.size() );
@@ -2824,47 +2822,47 @@ public class DnTest
new Dn( schemaManager, dn );
assertEquals( " OU = Ex\\+mple + cn = T\\+ST\\ , ou = COM ", dn.getName() );
- assertEquals( "OU=Ex\\+mple+cn=T\\+ST\\ ,ou=COM", dn.getEscaped() );
+ assertEquals( "cn=T\\+ST\\ +OU=Ex\\+mple,ou=COM", dn.getEscaped() );
// Check the first Rdn
rdn = dn.getRdn();
assertEquals( " OU = Ex\\+mple + cn = T\\+ST\\ ", rdn.getName() );
- assertEquals( "OU=Ex\\+mple+cn=T\\+ST\\ ", rdn.getEscaped() );
+ assertEquals( "cn=T\\+ST\\ +OU=Ex\\+mple", rdn.getEscaped() );
- assertEquals( "OU", rdn.getType() );
- assertEquals( "ou", rdn.getNormType() );
+ assertEquals( "cn", rdn.getType() );
+ assertEquals( "cn", rdn.getNormType() );
- assertEquals( "Ex+mple", rdn.getValue() );
+ assertEquals( "T+ST ", rdn.getValue() );
// The first ATAV
atav = rdn.getAva();
- assertEquals( " OU = Ex\\+mple ", atav.getName() );
- assertEquals( "OU=Ex\\+mple", atav.getEscaped() );
+ assertEquals( " cn = T\\+ST\\ ", atav.getName() );
+ assertEquals( "cn=T\\+ST\\ ", atav.getEscaped() );
- assertEquals( "ou", atav.getNormType() );
- assertEquals( "OU", atav.getType() );
+ assertEquals( "cn", atav.getNormType() );
+ assertEquals( "cn", atav.getType() );
- assertEquals( "Ex+mple", atav.getValue().getString() );
+ assertEquals( "T+ST ", atav.getValue().getString() );
assertEquals( 2, rdn.size() );
// The second ATAV
for ( Ava ava : rdn )
{
- if ( "Ex+mple".equals( ava.getValue().getString() ) )
+ if ( "T+ST ".equals( ava.getValue().getString() ) )
{
// Skip the first one
continue;
}
- assertEquals( " cn = T\\+ST\\ ", ava.getName() );
- assertEquals( "cn=T\\+ST\\ ", ava.getEscaped() );
+ assertEquals( " OU = Ex\\+mple ", ava.getName() );
+ assertEquals( "OU=Ex\\+mple", ava.getEscaped() );
- assertEquals( "cn", ava.getType() );
- assertEquals( "cn", ava.getNormType() );
+ assertEquals( "OU", ava.getType() );
+ assertEquals( "ou", ava.getNormType() );
- assertEquals( "T+ST ", ava.getValue().getString() );
+ assertEquals( "Ex+mple", ava.getValue().getString() );
}
}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
index 998491aed..ecdbd8362 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
@@ -85,7 +85,7 @@ public class FastParserRdnTest
errors += "\nRdn.getName fails '" + rdn.getName() + "'";
}
- if ( !"Cn=TEST".equals( rdn.getNormName() ) )
+ if ( !"cn=TEST".equals( rdn.getNormName() ) )
{
errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
index 9ec5139ae..0db15aca5 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/RdnTest.java
@@ -153,22 +153,22 @@ public class RdnTest
errors += "\nRdn.getName fails '" + rdn.getName() + "'";
}
- if ( !"OU=Exemple \\+ Rdn\u00E4\\ +cn=TEST" .equals( rdn.getEscaped() ) )
+ if ( !"cn=TEST+OU=Exemple \\+ Rdn\u00E4\\ " .equals( rdn.getEscaped() ) )
{
errors = "\nRdn.getEscaped fails '" + rdn.getEscaped() + "'";
}
- if ( !"ou".equals( rdn.getNormType() ) )
+ if ( !"cn".equals( rdn.getNormType() ) )
{
errors += "\nRdn.getNormType fails '" + rdn.getNormType() + "'";
}
- if ( !"Exemple + Rdn\u00E4 ".equals( rdn.getValue() ) )
+ if ( !"TEST".equals( rdn.getValue() ) )
{
- errors += "\nRdn.getEscaped fails '" + rdn.getValue() + "'";
+ errors += "\nRdn.getValue fails '" + rdn.getValue() + "'";
}
- if ( !"OU".equals( rdn.getType() ) )
+ if ( !"cn".equals( rdn.getType() ) )
{
errors += "\nRdn.getUpType fails '" + rdn.getType() + "'";
}
diff --git a/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnTest.java
similarity index 51%
copy from integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
copy to integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnTest.java
index 998491aed..a00abf6e0 100644
--- a/integ/src/test/java/org/apache/directory/api/ldap/model/name/FastParserRdnTest.java
+++ b/integ/src/test/java/org/apache/directory/api/ldap/model/name/SchemaAwareDnTest.java
@@ -6,95 +6,68 @@
* to you 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
- *
+ *
* https://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.directory.api.ldap.model.name;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
/**
- * Tests for the schemaAware Rdn class when using teh FastParser
- *
+ * Test the class Dn
+ *
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@Execution( ExecutionMode.CONCURRENT )
-public class FastParserRdnTest
+public class SchemaAwareDnTest
{
private static SchemaManager schemaManager;
+ /**
+ * Initialize OIDs maps for normalization
+ */
@BeforeAll
public static void setup() throws Exception
{
schemaManager = new DefaultSchemaManager();
}
-
-
- @Test
- public void testSimpleRdnValueSchemaAware() throws LdapException
- {
- String errors = null;
-
- Rdn rdn = new Rdn( schemaManager, "CommonName = TEST " );
-
- if ( !"CommonName = TEST ".equals( rdn.getName() ) )
- {
- errors += "\nRdn.getName fails '" + rdn.getName() + "'";
- }
-
- if ( !"2.5.4.3= test ".equals( rdn.getNormName() ) )
- {
- errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
- }
-
- if ( !"TEST".equals( rdn.getValue( "cn" ) ) )
- {
- errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getValue( "cn" ) + "'";
- }
-
- assertEquals( null, errors );
- }
-
-
+
+ /**
+ * test a simple Dn with multiple NameComponents : cn=Kate + sn=Bush,ou=system
+ */
@Test
- public void testSimpleRdnValueNullSchemaManager() throws LdapException
+ @Disabled
+ public void testDnSimpleMultivaluedAttribute() throws LdapException
{
- String errors = null;
-
- Rdn rdn = new Rdn( (SchemaManager)null, "Cn= TEST " );
-
- if ( !"Cn= TEST ".equals( rdn.getName() ) )
- {
- errors += "\nRdn.getName fails '" + rdn.getName() + "'";
- }
-
- if ( !"Cn=TEST".equals( rdn.getNormName() ) )
- {
- errors = "\nRdn.getNormName fails '" + rdn.getNormName() + "'";
- }
-
- if ( !"TEST".equals( rdn.getValue( "cn" ) ) )
- {
- errors += "\nRdn.getNormValue( 'cn' ) fails '" + ( String ) rdn.getValue( "cn" ) + "'";
- }
+ Dn dn = new Dn( schemaManager, "cn=Kate+sn=Bush,ou=system" );
+
+ assertTrue( Dn.isValid( "cn=Kate+sn=Bush,ou=system" ) );
+ assertEquals( "2.5.4.3= kate +2.5.4.4= bush ,2.5.4.11= system ", dn.getNormName() );
+
+ Dn dn2 = new Dn( schemaManager, "sn=Bush+cn=Kate,ou=system" );
+
+ assertTrue( Dn.isValid( "sn=Bush+cn=Kate,ou=system" ) );
+ assertEquals( "2.5.4.3= kate +2.5.4.4= bush ,2.5.4.11= system ", dn2.getNormName() );
- assertEquals( null, errors );
+ assertEquals( dn, dn2 );
}
}
diff --git a/ldap/model/src/main/antlr/distinguishedName.g b/ldap/model/src/main/antlr/distinguishedName.g
index 04b7d646a..c71c1eef7 100644
--- a/ldap/model/src/main/antlr/distinguishedName.g
+++ b/ldap/model/src/main/antlr/distinguishedName.g
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import javax.naming.NameParser;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
@@ -164,6 +165,32 @@ options {
// A flag set to false if we have a binary value
boolean isHR = true;
}
+
+
+ private String createNormAva( Ava ava )
+ {
+ StringBuilder rdnNormStr = new StringBuilder();
+ Value value = ava.getValue();
+ AttributeType attributeType = ava.getAttributeType();
+ rdnNormStr.append( ava.getNormType() );
+ rdnNormStr.append( '=' );
+
+ if ( value != null )
+ {
+ if ( value.getNormalized() != null )
+ {
+ rdnNormStr.append( value.getNormalized() );
+ }
+ else
+ {
+ // We can't tell if the value is HR or not.
+ // Use the Value User Provided value
+ rdnNormStr.append( value.getUpValue() );
+ }
+ }
+
+ return rdnNormStr.toString();
+ }
}
@@ -302,6 +329,7 @@ relativeDistinguishedNames [SchemaManager schemaManager, List<Rdn> rdns] returns
}
;
+
/**
* Parses a Rdn string.
*
@@ -335,120 +363,123 @@ relativeDistinguishedName [SchemaManager schemaManager, Rdn rdn]
// The rdnStr variable is used to gather the full RDN string
// as provided
- StringBuilder rdnStr = new StringBuilder();
+ StringBuilder rdnUpStr = new StringBuilder();
StringBuilder rdnNormStr = new StringBuilder();
int avaPos = 0;
- Ava currentAva;
AttributeType attributeType;
Value val;
+ Ava ava = new Ava( schemaManager);
+ String upAva;
+
+ // The list of parsed Ava for a later post-processing
+ List<Ava> avas = new ArrayList<>();
}
:
(
- tmp = attributeTypeAndValue[schemaManager, rdn]
+ // The first AVA
+ upAva = attributeTypeAndValue[schemaManager, ava]
{
- rdnStr.append( tmp );
- currentAva = rdn.getAva( avaPos );
-
- attributeType = currentAva.getAttributeType();
-
- if ( schemaManager == null )
+ ava.hashCode();
+ rdnUpStr.append( upAva );
+ avas.add( ava );
+ }
+ (
+ PLUS
{
- rdnNormStr.append( currentAva.getNormType() );
- rdnNormStr.append( '=' );
+ ava = new Ava( schemaManager);
}
-
- val = currentAva.getValue();
-
- if ( ( schemaManager == null ) && ( val != null ) )
+ upAva = attributeTypeAndValue[schemaManager, ava]
{
- if ( val.getNormalized() != null )
- {
- rdnNormStr.append( val.getNormalized() );
- }
- else
+ ava.hashCode();
+ rdnUpStr.append( '+' ).append( upAva );
+
+ try
{
- // We can't tell if the value is HR or not.
- // Use the Value User Provided value
- rdnNormStr.append( val.getUpValue() );
+ Rdn.addOrdered( avas, ava );
}
- }
- }
- (
- PLUS
- {
- rdnStr.append( '+' );
-
- if ( schemaManager == null )
+ catch ( LdapInvalidDnException lide )
{
- rdnNormStr.append( '+' );
+ throw new SemanticException( lide.getMessage() );
}
-
- avaPos++;
}
+ )*
+ )
+ {
+ // Now, build the Rdn
+ switch ( avas.size() )
+ {
+ case 0:
+ // Can't be...
+ case 1:
+ // One single Ava
+ rdn.upName = rdnUpStr.toString();
+ rdn.normName = createNormAva( ava );
+ rdn.ava = ava;
+ rdn.avaType = ava.getType();
+ rdn.nbAvas = 1;
+ break;
- tmp = attributeTypeAndValue[schemaManager, rdn]
- {
- rdnStr.append( tmp );
- currentAva = rdn.getAva( avaPos );
- attributeType = currentAva.getAttributeType();
-
- if ( schemaManager == null )
+ default:
+ rdn.nbAvas = avas.size();
+ rdn.avaTypes = new HashMap<String, List<Ava>>();
+ boolean isFirst = true;
+
+ for ( Ava parsedAva : avas )
{
- rdnNormStr.append( tmp );
+ if ( isFirst )
+ {
+ isFirst = false;
+ }
+ else
+ {
+ rdnNormStr.append( '+' );
+ }
+
+ String type;
+
+ if ( schemaManager != null )
+ {
+ type = parsedAva.getAttributeType().getOid();
+ rdnNormStr.append( type );
+ }
+ else
+ {
+ type = parsedAva.normType;
+ rdnNormStr.append( type );
+ }
+
rdnNormStr.append( '=' );
- }
-
- val = currentAva.getValue();
-
- if ( ( schemaManager == null ) && ( val != null ) )
- {
- if ( val.getNormalized() != null )
+
+ val = parsedAva.getValue();
+
+ if ( ( val != null ) && ( val.getNormalized() != null ) )
{
rdnNormStr.append( val.getNormalized() );
}
else
{
- // We can't tell if the value is HR or not.
- // Use the Value User Provided value
rdnNormStr.append( val.getUpValue() );
}
- }
- }
- )*
- )
- {
- rdn.hashCode();
- rdn.setUpName( rdnStr.toString() );
-
- if ( schemaManager != null )
- {
- // process the multi-value RDN, ordering them by attributes
- boolean isFirst = true;
-
- for ( Ava ava : rdn )
- {
- if ( isFirst )
- {
- isFirst = false;
- }
- else
- {
- rdnNormStr.append( '+' );
- }
-
- rdnNormStr.append( ava.getAttributeType().getOid() );
- rdnNormStr.append( '=' );
-
- val = ava.getValue();
- if ( ( val != null ) && ( val.getNormalized() != null ) )
- {
- rdnNormStr.append( val.getNormalized() );
+ List<Ava> avaList = rdn.avaTypes.get( type );
+
+ if ( avaList == null )
+ {
+ avaList = new ArrayList<>();
+ }
+
+ avaList.add( parsedAva );
+ rdn.avaTypes.put( type, avaList );
}
- }
+
+ rdn.upName = rdnUpStr.toString();
+ rdn.normName = rdnNormStr.toString();
+ rdn.avas = avas;
+
+ break;
}
-
- rdn.setNormName( rdnNormStr.toString() );
+
+ rdn.hashCode();
}
;
@@ -465,12 +496,12 @@ relativeDistinguishedName [SchemaManager schemaManager, Rdn rdn]
* </pre>
*
* @param schemaManager The SchemaManager
- * @param rdn The Rdn to update
+ * @param ava The parsed Ava
* @return The user provided Ava
* @throws RecognitionException If the token is invalid
* @throws TokenStreamException When we weren't able to fetch a token
*/
-attributeTypeAndValue [SchemaManager schemaManager, Rdn rdn] returns [String upNameStr]
+attributeTypeAndValue [SchemaManager schemaManager, Ava ava] returns [String upNameStr]
{
matchedProduction( "attributeTypeAndValue()" );
String type = null;
@@ -492,7 +523,6 @@ attributeTypeAndValue [SchemaManager schemaManager, Rdn rdn] returns [String upN
// cannot be processed
rdnUpName.append( value.upValue );
AttributeType attributeType = null;
- Ava ava = null;
if ( schemaManager != null )
{
@@ -502,6 +532,14 @@ attributeTypeAndValue [SchemaManager schemaManager, Rdn rdn] returns [String upN
}
attributeType = schemaManager.getAttributeType( type );
+ ava.attributeType = attributeType;
+ ava.upType = type;
+ ava.normType = attributeType.getOid();
+ }
+ else
+ {
+ ava.upType = type;
+ ava.normType = Strings.lowerCaseAscii( Strings.trim( type ) );
}
if ( ( ( attributeType != null ) && attributeType.isHR() ) || value.isHR )
@@ -538,17 +576,45 @@ attributeTypeAndValue [SchemaManager schemaManager, Rdn rdn] returns [String upN
}
}
- if ( ava == null )
+ if ( attributeType != null )
+ {
+ try
+ {
+ if ( ava == null )
+ {
+ ava.upName = rdnUpName.toString();
+ ava.value = new Value( attributeType, Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
+ }
+ else
+ {
+ ava.upName = rdnUpName.toString();
+ ava.value = new Value( attributeType, Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
+ }
+ }
+ catch ( LdapInvalidAttributeValueException liave )
+ {
+ throw new SemanticException( liave.getMessage() );
+ }
+ }
+ else
{
- ava = new Ava( schemaManager, type, rdnUpName.toString(), Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
+ if ( ava == null )
+ {
+ ava.upName = rdnUpName.toString();
+ ava.value = new Value( Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
+ }
+ else
+ {
+ ava.upName = rdnUpName.toString();
+ ava.value = new Value( Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
+ }
}
}
else
{
- ava = new Ava( schemaManager, type, rdnUpName.toString(), value.bytes.copyOfUsedBytes() );
+ ava.upName = rdnUpName.toString();
+ ava.value = new Value( value.bytes.copyOfUsedBytes() );
}
-
- rdn.addAVA( schemaManager, ava );
}
catch ( LdapInvalidDnException e )
{
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
index 34721b31f..1604dad3a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/LdifRevertor.java
@@ -426,7 +426,7 @@ public final class LdifRevertor
reverted.setDn( newDn );
}
- reverted.setNewRdn( oldRdn.getName() );
+ reverted.setNewRdn( oldRdn.getNormName() );
if ( newSuperior != null )
{
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
index 8feafbff8..03133d625 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
@@ -77,19 +77,19 @@ public class Ava implements Externalizable, Cloneable, Comparable<Ava>
private static final Logger LOG = LoggerFactory.getLogger( Ava.class );
/** The normalized Name type */
- private String normType;
+ /* package protected */ String normType;
/** The user provided Name type */
- private String upType;
+ /* package protected */ String upType;
/** The value. It can be a String or a byte array */
- private Value value;
+ /* package protected */ Value value;
/** The user provided Ava */
- private String upName;
+ /* package protected */ String upName;
/** The attributeType if the Ava is schemaAware */
- private AttributeType attributeType;
+ /* package protected */ AttributeType attributeType;
/** the schema manager */
private transient SchemaManager schemaManager;
@@ -1295,6 +1295,46 @@ public class Ava implements Externalizable, Cloneable, Comparable<Ava>
{
return attributeType;
}
+
+
+ /* Package protected */ void setAttributeType( SchemaManager schemaManager, String upType )
+ throws LdapInvalidDnException
+ {
+ if ( schemaManager != null )
+ {
+ this.schemaManager = schemaManager;
+
+ try
+ {
+ attributeType = schemaManager.lookupAttributeTypeRegistry( upType );
+ }
+ catch ( LdapException le )
+ {
+ String message = I18n.err( I18n.ERR_13600_TYPE_IS_NULL_OR_EMPTY );
+ throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
+ }
+
+ normType = attributeType.getOid();
+ }
+ else
+ {
+ String upTypeTrimmed = Strings.trim( upType );
+
+ if ( Strings.isEmpty( upTypeTrimmed ) )
+ {
+ String message = I18n.err( I18n.ERR_13600_TYPE_IS_NULL_OR_EMPTY );
+ // Do NOT log the message here. The error may be handled and therefore the log message may polute the log files.
+ // Let the caller log the exception if needed.
+ throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message );
+ }
+ else
+ {
+ // In this case, we will use the upType instead
+ this.normType = Strings.lowerCaseAscii( upTypeTrimmed );
+ this.upType = upType;
+ }
+ }
+ }
private int compareValues( Ava that )
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
index ecdb23bb0..40685134a 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
@@ -107,6 +107,10 @@ public class Dn implements Iterable<Rdn>, Externalizable
/** the schema manager */
private transient SchemaManager schemaManager;
+
+ /** Two constants used to trim the DN UpName */
+ private static final boolean LEFT = true;
+ private static final boolean RIGHT = false;
/**
* An iterator over RDNs
@@ -197,7 +201,7 @@ public class Dn implements Iterable<Rdn>, Externalizable
this.rdns.add( new Rdn( schemaManager, rdn ) );
}
- toUpName();
+ upName = toUpName();
}
@@ -755,7 +759,7 @@ public class Dn implements Iterable<Rdn>, Externalizable
/**
- * Get the descendant of a given DN, using the ancestr DN. Assuming that
+ * Get the descendant of a given DN, using the ancestor DN. Assuming that
* a DN has two parts :<br>
* DN = [descendant DN][ancestor DN]<br>
* To get back the descendant from the full DN, you just pass the ancestor DN
@@ -807,6 +811,12 @@ public class Dn implements Iterable<Rdn>, Externalizable
}
}
+ // Short cut: if the last RDNs are equal, return ""
+ if ( rdns.get( 0 ).equals( rdnsAncestor.get( 0 ) ) )
+ {
+ return newDn;
+ }
+
for ( int i = 0; i < rdns.size() - length; i++ )
{
newDn.rdns.add( rdns.get( i ) );
@@ -862,25 +872,25 @@ public class Dn implements Iterable<Rdn>, Externalizable
*/
public Dn getAncestorOf( Dn descendant ) throws LdapInvalidDnException
{
- if ( ( descendant == null ) || ( descendant.size() == 0 ) )
+ int length = descendant.size();
+
+ if ( ( descendant == null ) || ( length == 0 ) )
{
return this;
}
- if ( rdns.isEmpty() )
+ if ( rdns.isEmpty() || length == rdns.size() )
{
return EMPTY_DN;
}
- int length = descendant.size();
-
if ( length > rdns.size() )
{
String message = I18n.err( I18n.ERR_13612_POSITION_NOT_IN_RANGE, length, rdns.size() );
LOG.error( message );
throw new ArrayIndexOutOfBoundsException( message );
}
-
+
Dn newDn = new Dn( schemaManager );
List<Rdn> rdnsDescendant = descendant.getRdns();
@@ -900,7 +910,7 @@ public class Dn implements Iterable<Rdn>, Externalizable
newDn.rdns.add( rdns.get( i ) );
}
- newDn.toUpName();
+ newDn.upName = upName.substring( descendant.upName.length() + 1 );
return newDn;
}
@@ -993,6 +1003,7 @@ public class Dn implements Iterable<Rdn>, Externalizable
clonedDn.rdns.add( 0, new Rdn( schemaManager, newRdn ) );
clonedDn.toUpName();
+ clonedDn.upName = newRdn.upName + ',' + upName;
return clonedDn;
}
@@ -1021,10 +1032,40 @@ public class Dn implements Iterable<Rdn>, Externalizable
newDn.rdns.add( rdns.get( i ) );
}
- newDn.toUpName();
+ newDn.upName = removeUpName( rdns.get( 0 ).upName, LEFT );
return newDn;
}
+
+
+ private String removeUpName( String removedUpName, boolean fromLeft )
+ {
+ int removedSize = removedUpName.length();
+
+ if ( fromLeft )
+ {
+ for ( int i = removedSize; i < upName.length(); i++ )
+ {
+ if ( upName.charAt( i ) == ',' )
+ {
+ return upName.substring( i + 1 );
+ }
+ }
+ }
+ else
+ {
+ for ( int i = upName.length() - removedSize; i > 0; i-- )
+ {
+ if ( upName.charAt( i ) == ',' )
+ {
+ return upName.substring( 0, i - 1 );
+ }
+ }
+ }
+
+ // Nothing left
+ return Strings.EMPTY_STRING;
+ }
/**
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
index fd356123a..2f9c8d95b 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
@@ -215,7 +215,7 @@ import org.apache.directory.api.util.Strings;
}
else
{
- sbNormName.append( type );
+ sbNormName.append( Strings.toLowerCaseAscii( type ) );
sbNormName.append( '=' );
sbNormName.append( upValue );
}
diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
index 842b652be..7c94b53e6 100644
--- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
+++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Rdn.java
@@ -129,10 +129,10 @@ public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable
private static final long serialVersionUID = 1L;
/** The User Provided Rdn */
- private String upName = null;
+ /* package protected */ String upName = null;
/** The normalized Rdn */
- private String normName;
+ /* package protected */ String normName;
/**
* Stores all couple type = value. We may have more than one type, if the
@@ -140,31 +140,31 @@ public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable
* because we want the Avas to be sorted. An Ava may contain more than one
* value. In this case, the values are String stored in a List.
*/
- private transient List<Ava> avas = null;
+ /* package protected */ transient List<Ava> avas = null;
/**
* We also keep a set of types, in order to use manipulations. A type is
* connected with the Ava it represents.
*/
- private transient Map<String, List<Ava>> avaTypes;
+ /* package protected */ transient Map<String, List<Ava>> avaTypes;
/**
* We keep the type for a single valued Rdn, to avoid the creation of an HashMap
*/
- private String avaType = null;
+ /* package protected */ String avaType = null;
/**
* A simple Ava is used to store the Rdn for the simple
* case where we only have a single type=value. This will be 99.99% the
* case. This avoids the creation of a HashMap.
*/
- protected Ava ava = null;
+ /* package protected */ Ava ava = null;
/**
* The number of Avas. We store this number here to avoid complex
* manipulation of Ava and Avas
*/
- private int nbAvas = 0;
+ /* package protected */ int nbAvas = 0;
/** CompareTo() results */
public static final int UNDEFINED = Integer.MAX_VALUE;
@@ -225,6 +225,8 @@ public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable
*/
public Rdn( SchemaManager schemaManager, String rdn ) throws LdapInvalidDnException
{
+ this.schemaManager = schemaManager;
+
if ( Strings.isNotEmpty( rdn ) )
{
// Parse the string. The Rdn will be updated.
@@ -530,7 +532,7 @@ public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable
* @param newAva The Ava to add
* @return The list of Ava with the new Ava at the right position
*/
- /*package protected*/ static List<Ava> addOrdered( List<Ava> avaList, Ava newAva )
+ /*package protected*/ static List<Ava> addOrdered( List<Ava> avaList, Ava newAva ) throws LdapInvalidDnException
{
if ( avaList == null )
{
@@ -561,7 +563,8 @@ public class Rdn implements Cloneable, Externalizable, Iterable<Ava>, Comparable
else if ( comp == 0 )
{
found = true;
- break;
+
+ throw new LdapInvalidDnException( I18n.err( I18n.ERR_13626_INVALID_RDN_DUPLICATE_AVA, avaElem.normType ) );
}
else
{
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifRevertorTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifRevertorTest.java
index 788e5b1cc..bf92ee58a 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifRevertorTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/ldif/LdifRevertorTest.java
@@ -1575,7 +1575,7 @@ public class LdifRevertorTest
assertEquals( "cn=joe+sn=plumber,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertTrue( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
@@ -1624,7 +1624,7 @@ public class LdifRevertorTest
assertEquals( "sn=joe+cn=big,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertFalse( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
reversed = reverseds.get( 1 );
@@ -1686,7 +1686,7 @@ public class LdifRevertorTest
assertEquals( "cn=joe+sn=plumber,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertTrue( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
@@ -1735,7 +1735,7 @@ public class LdifRevertorTest
assertEquals( "cn=joe+sn=big,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertFalse( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
reversed = reverseds.get( 1 );
@@ -1797,7 +1797,7 @@ public class LdifRevertorTest
assertEquals( "sn=joe+cn=test,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertTrue( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
@@ -1846,7 +1846,7 @@ public class LdifRevertorTest
assertEquals( "sn=big+cn=test,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertFalse( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
@@ -1895,7 +1895,7 @@ public class LdifRevertorTest
assertEquals( "sn=joe+cn=test,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertTrue( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
@@ -1944,7 +1944,7 @@ public class LdifRevertorTest
assertEquals( "sn=big+cn=test,ou=system", reversed.getDn().getName() );
assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
assertFalse( reversed.isDeleteOldRdn() );
- assertEquals( oldRdn.getName(), reversed.getNewRdn() );
+ assertEquals( oldRdn.getNormName(), reversed.getNewRdn() );
assertNull( reversed.getNewSuperior() );
}
}
diff --git a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
index c82dc95ef..b5cc0d3a6 100644
--- a/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
+++ b/ldap/model/src/test/java/org/apache/directory/api/ldap/model/name/DnParserTest.java
@@ -401,7 +401,7 @@ public class DnParserTest
assertEquals( "OU = Sales + CN = J. Smith , O = Widget Inc. , C = US",
nameRFC2253_2.getName(), "RFC2253_2 : " );
- assertEquals( "OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", nameRFC2253_2.getEscaped(), "RFC2253_2 : " );
+ assertEquals( "CN=J. Smith+OU=Sales,O=Widget Inc.,C=US", nameRFC2253_2.getEscaped(), "RFC2253_2 : " );
}
@@ -658,7 +658,7 @@ public class DnParserTest
try
{
- String dnStr = "workforceID=2# + a=b";
+ String dnStr = "workforceID=2# + z=b";
assertTrue( Dn.isValid( dnStr ) );
Dn dn = new Dn( dnStr );