You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2008/08/27 18:57:11 UTC

svn commit: r689524 - in /directory/shared/trunk/ldap/src: main/java/org/apache/directory/shared/ldap/util/LdapURL.java test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java

Author: seelmann
Date: Wed Aug 27 09:57:11 2008
New Revision: 689524

URL: http://svn.apache.org/viewvc?rev=689524&view=rev
Log:
Partial fix for DIRSHARED-18: using a List for extensions, enabled tests.

Modified:
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/LdapURL.java
    directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/LdapURL.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/LdapURL.java?rev=689524&r1=689523&r2=689524&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/LdapURL.java (original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/LdapURL.java Wed Aug 27 09:57:11 2008
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -105,22 +106,25 @@
     /** The filter as a string */
     private String filter;
 
-    /** The extensions */
-    private Map<String, String> extensions;
-
-    /** The criticals extensions */
-    private Map<String, String> criticalExtensions;
+    /** The extensions. */
+    private List<Extension> extensionList;
+    //
+    //    /** The extensions */
+    //    private Map<String, String> extensions;
+    //
+    //    /** The criticals extensions */
+    //    private Map<String, String> criticalExtensions;
 
     /** Stores the LdapURL as a String */
     private String string;
 
     /** Stores the LdapURL as a byte array */
     private byte[] bytes;
-    
+
     /** modal parameter that forces explicit scope rendering in toString */
     private boolean forceScopeRendering;
-    
-    
+
+
     // ~ Constructors
     // -------------------------------------------------------------------------------
 
@@ -136,10 +140,12 @@
         attributes = new ArrayList<String>();
         scope = SearchControls.OBJECT_SCOPE;
         filter = null;
-        extensions = new HashMap<String, String>();
-        criticalExtensions = new HashMap<String, String>();
+        extensionList = new ArrayList<Extension>( 2 );
+        //        extensions = new HashMap<String, String>();
+        //        criticalExtensions = new HashMap<String, String>();
     }
 
+
     /**
      * Parse a LdapURL
      * @param chars The chars containing the URL
@@ -154,8 +160,9 @@
         attributes = new ArrayList<String>();
         scope = SearchControls.OBJECT_SCOPE;
         filter = null;
-        extensions = new HashMap<String, String>();
-        criticalExtensions = new HashMap<String, String>();
+        extensionList = new ArrayList<Extension>( 2 );
+        //        extensions = new HashMap<String, String>();
+        //        criticalExtensions = new HashMap<String, String>();
 
         if ( ( chars == null ) || ( chars.length == 0 ) )
         {
@@ -336,7 +343,7 @@
      * @param bytes The byte buffer that contains the LDAPURL
      * @throws LdapURLEncodingException If the byte array does not comply with RFC 2255
      */
-    public LdapURL(byte[] bytes) throws LdapURLEncodingException
+    public LdapURL( byte[] bytes ) throws LdapURLEncodingException
     {
         if ( ( bytes == null ) || ( bytes.length == 0 ) )
         {
@@ -345,7 +352,7 @@
 
         string = StringTools.utf8ToString( bytes );
 
-        this.bytes = new byte[ bytes.length ];
+        this.bytes = new byte[bytes.length];
         System.arraycopy( bytes, 0, this.bytes, 0, bytes.length );
 
         parse( string.toCharArray() );
@@ -571,7 +578,7 @@
     private int parseHostPort( char[] chars, int pos )
     {
         int hostPos = pos;
-        
+
         if ( ( pos = parseHost( chars, pos ) ) == -1 )
         {
             return -1;
@@ -585,7 +592,7 @@
                 // We should not have a port if we have no host
                 return -1;
             }
-            
+
             pos++;
         }
         else
@@ -923,7 +930,7 @@
             // We have no filter
             return end;
         }
-        
+
         try
         {
             filter = decode( new String( chars, pos, end - pos ) );
@@ -1037,7 +1044,6 @@
      */
     private int parseExtensions( char[] chars, int pos )
     {
-
         int start = pos;
         boolean isCritical = false;
         boolean isNewExtension = true;
@@ -1052,38 +1058,30 @@
 
         try
         {
-
             for ( int i = pos; ( i < chars.length ); i++ )
             {
-
                 if ( StringTools.isCharASCII( chars, i, ',' ) )
                 {
-
                     if ( isNewExtension )
                     {
-
                         // a ',' is not allowed when we have already had one
                         // or if we just started to parse the extensions.
                         return -1;
                     }
                     else
                     {
-                        value = decode( new String( chars, start, i - start ) ).trim();
-
-                        if ( value.length() == 0 )
+                        if ( extension == null )
                         {
-                            return -1;
-                        }
-
-                        if ( isCritical )
-                        {
-                            criticalExtensions.put( extension, value );
+                            extension = decode( new String( chars, start, i - start ) ).trim();
                         }
                         else
                         {
-                            extensions.put( extension, value );
+                            value = decode( new String( chars, start, i - start ) ).trim();
                         }
 
+                        Extension ext = new Extension( isCritical, extension, value );
+                        extensionList.add( ext );
+
                         isNewExtension = true;
                         hasValue = false;
                         isCritical = false;
@@ -1094,10 +1092,8 @@
                 }
                 else if ( StringTools.isCharASCII( chars, i, '=' ) )
                 {
-
                     if ( hasValue )
                     {
-
                         // We may have two '=' for the same extension
                         continue;
                     }
@@ -1107,21 +1103,17 @@
 
                     if ( extension.length() == 0 )
                     {
-
                         // We must have an extension
                         return -1;
                     }
 
-                    isNewExtension = false;
                     hasValue = true;
                     start = i + 1;
                 }
                 else if ( StringTools.isCharASCII( chars, i, '!' ) )
                 {
-
                     if ( !isNewExtension )
                     {
-
                         // '!' must appears first
                         return -1;
                     }
@@ -1129,6 +1121,10 @@
                     isCritical = true;
                     start++;
                 }
+                else
+                {
+                    isNewExtension = false;
+                }
             }
 
             if ( extension == null )
@@ -1140,14 +1136,8 @@
                 value = decode( new String( chars, start, chars.length - start ) ).trim();
             }
 
-            if ( isCritical )
-            {
-                criticalExtensions.put( extension, value );
-            }
-            else
-            {
-                extensions.put( extension, value );
-            }
+            Extension ext = new Extension( isCritical, extension, value );
+            extensionList.add( ext );
 
             return chars.length;
         }
@@ -1206,7 +1196,7 @@
 
                 default:
                     sb.append( c );
-                break;
+                    break;
             }
         }
 
@@ -1238,14 +1228,13 @@
             sb.append( '/' ).append( urlEncode( dn.toString(), false ) );
 
             if ( attributes.size() != 0 || forceScopeRendering
-                || ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || 
-                    ( extensions.size() != 0 ) || ( criticalExtensions.size() != 0 ) ) )
+                || ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || ( extensionList.size() != 0 ) ) )
             {
                 sb.append( '?' );
 
                 boolean isFirst = true;
-                
-                for ( String attribute:attributes )
+
+                for ( String attribute : attributes )
                 {
                     if ( isFirst )
                     {
@@ -1259,7 +1248,7 @@
                     sb.append( urlEncode( attribute, false ) );
                 }
             }
-            
+
             if ( forceScopeRendering )
             {
                 sb.append( '?' );
@@ -1278,61 +1267,57 @@
                     case SearchControls.SUBTREE_SCOPE:
                         sb.append( "sub" );
                         break;
-                        
-                        
-                    default :
+
+                    default:
                         break;
                 }
             }
 
             else
             {
-                if ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || ( extensions.size() != 0 )
-                    || ( criticalExtensions.size() != 0 ) )
+                if ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || ( extensionList.size() != 0 ) )
                 {
                     sb.append( '?' );
-    
+
                     switch ( scope )
                     {
-    
+
                         case SearchControls.OBJECT_SCOPE:
-    
+
                             // This is the default value.
                             break;
-    
+
                         case SearchControls.ONELEVEL_SCOPE:
                             sb.append( "one" );
                             break;
-    
+
                         case SearchControls.SUBTREE_SCOPE:
                             sb.append( "sub" );
                             break;
-                            
-                            
-                        default :
+
+                        default:
                             break;
                     }
-    
-                    if ( ( filter != null ) || ( ( extensions.size() != 0 ) || ( criticalExtensions.size() != 0 ) ) )
+
+                    if ( ( filter != null ) || ( ( extensionList.size() != 0 ) ) )
                     {
                         sb.append( "?" );
-    
+
                         if ( filter != null )
                         {
                             sb.append( urlEncode( filter, false ) );
                         }
-    
-                        if ( ( extensions.size() != 0 ) || ( criticalExtensions.size() != 0 ) )
+
+                        if ( ( extensionList.size() != 0 ) )
                         {
                             sb.append( '?' );
-    
+
                             boolean isFirst = true;
-    
-                            if ( extensions.size() != 0 )
+
+                            if ( extensionList.size() != 0 )
                             {
-                                for ( String key:extensions.keySet() )
+                                for ( Extension extension : extensionList )
                                 {
-    
                                     if ( !isFirst )
                                     {
                                         sb.append( ',' );
@@ -1341,37 +1326,17 @@
                                     {
                                         isFirst = false;
                                     }
-    
-                                    sb.append( urlEncode( key, false ) ).append( '=' ).append(
-                                        urlEncode( extensions.get( key ), true ) );
-                                }
-                            }
-    
-                            isFirst = true;
-    
-                            if ( criticalExtensions.size() != 0 )
-                            {
-                                for ( String key:criticalExtensions.keySet() )
-                                {
-    
-                                    if ( !isFirst )
-                                    {
-                                        sb.append( ",!" );
-                                    }
-                                    else
+
+                                    if ( extension.isCritical )
                                     {
                                         sb.append( '!' );
-                                        isFirst = false;
                                     }
-    
-                                    sb.append( urlEncode( key, false ) );
-                                    
-                                    String value = criticalExtensions.get( key );
-                                    
-                                    if ( value != null )
+                                    sb.append( urlEncode( extension.type, false ) );
+
+                                    if ( extension.value != null )
                                     {
-                                        sb.append( '=' ).append(
-                                        urlEncode( value, true ) );
+                                        sb.append( '=' );
+                                        sb.append( urlEncode( extension.value, true ) );
                                     }
                                 }
                             }
@@ -1388,6 +1353,7 @@
         return sb.toString();
     }
 
+
     /**
      * @return Returns the attributes.
      */
@@ -1402,6 +1368,16 @@
      */
     public Map<String, String> getCriticalExtensions()
     {
+        Map<String, String> criticalExtensions = new HashMap<String, String>();
+
+        for ( Extension extension : extensionList )
+        {
+            if ( extension.isCritical )
+            {
+                criticalExtensions.put( extension.type, extension.value );
+            }
+        }
+
         return criticalExtensions;
     }
 
@@ -1420,6 +1396,16 @@
      */
     public Map<String, String> getExtensions()
     {
+        Map<String, String> extensions = new HashMap<String, String>();
+
+        for ( Extension extension : extensionList )
+        {
+            if ( extension.isCritical )
+            {
+                extensions.put( extension.type, extension.value );
+            }
+        }
+
         return extensions;
     }
 
@@ -1470,7 +1456,8 @@
     {
         return scheme;
     }
-    
+
+
     /**
      * @return the number of bytes for this LdapURL
      */
@@ -1478,7 +1465,8 @@
     {
         return ( bytes != null ? bytes.length : 0 );
     }
-    
+
+
     /**
      * @return a reference on the interned bytes representing this LdapURL
      */
@@ -1486,7 +1474,8 @@
     {
         return bytes;
     }
-    
+
+
     /**
      * @return a copy of the bytes representing this LdapURL
      */
@@ -1503,7 +1492,8 @@
             return null;
         }
     }
-    
+
+
     /**
      * @return the LdapURL as a String
      */
@@ -1512,6 +1502,7 @@
         return string;
     }
 
+
     /**
      * Compute the instance's hash code
      * @return the instance's hash code 
@@ -1521,6 +1512,7 @@
         return this.toString().hashCode();
     }
 
+
     public boolean equals( Object obj )
     {
         if ( this == obj )
@@ -1535,12 +1527,12 @@
         {
             return false;
         }
-        
+
         final LdapURL other = ( LdapURL ) obj;
         return this.toString().equals( other.toString() );
     }
 
-    
+
     /**
      * Sets the scheme. Must be "ldap://" or "ldaps://", otherwise "ldap://" is assumed as default.
      * 
@@ -1656,13 +1648,23 @@
      */
     public void setExtensions( Map<String, String> extensions )
     {
-        if ( extensions == null )
+        // remove all old non-critical extensions
+        for ( Iterator<Extension> it = extensionList.iterator(); it.hasNext(); )
         {
-            this.extensions.clear();
+            if ( !it.next().isCritical )
+            {
+                it.remove();
+            }
         }
-        else
+
+        // add new non-critical extensions 
+        if ( extensions != null )
         {
-            this.extensions = extensions;
+            for ( String key : extensions.keySet() )
+            {
+                Extension extension = new Extension( false, key, extensions.get( key ) );
+                extensionList.add( extension );
+            }
         }
     }
 
@@ -1674,17 +1676,27 @@
      */
     public void setCriticalExtensions( Map<String, String> criticalExtensions )
     {
-        if ( criticalExtensions == null )
+        // remove all old critical extensions
+        for ( Iterator<Extension> it = extensionList.iterator(); it.hasNext(); )
         {
-            this.criticalExtensions.clear();
+            if ( it.next().isCritical )
+            {
+                it.remove();
+            }
         }
-        else
+
+        // add new critical extensions 
+        if ( criticalExtensions != null )
         {
-            this.criticalExtensions = criticalExtensions;
+            for ( String key : criticalExtensions.keySet() )
+            {
+                Extension extension = new Extension( true, key, criticalExtensions.get( key ) );
+                extensionList.add( extension );
+            }
         }
     }
 
-    
+
     /**
      * If set to true forces the toString method to render the scope 
      * regardless of optional nature.  Use this when you want explicit
@@ -1697,7 +1709,7 @@
         this.forceScopeRendering = forceScopeRendering;
     }
 
-    
+
     /**
      * If set to true forces the toString method to render the scope 
      * regardless of optional nature.  Use this when you want explicit
@@ -1710,4 +1722,20 @@
         return forceScopeRendering;
     }
 
+    private class Extension
+    {
+        private boolean isCritical;
+        private String type;
+        private String value;
+
+
+        private Extension( boolean isCritical, String extype, String exvalue )
+        {
+            super();
+            this.isCritical = isCritical;
+            this.type = extype;
+            this.value = exvalue;
+        }
+    }
+
 }

Modified: directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java?rev=689524&r1=689523&r2=689524&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java (original)
+++ directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/LdapUrlTest.java Wed Aug 27 09:57:11 2008
@@ -31,9 +31,7 @@
 
 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
 import org.apache.directory.shared.ldap.name.LdapDN;
-import org.apache.directory.shared.ldap.util.LdapURL;
 import org.junit.Test;
-import org.junit.Ignore;
 
 
 /**
@@ -41,7 +39,6 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@Ignore
 public class LdapUrlTest extends TestCase
 {
     // ~ Methods
@@ -790,7 +787,7 @@
         Assert.assertEquals( "ldap:///dc=example,dc=com", url.toString() );
     }
 
-    
+
     /**
      * test a LdapURL without a scheme
      *
@@ -820,9 +817,9 @@
         try
         {
             LdapURL url = new LdapURL( "ldap:///ou=system" );
-            
+
             assertEquals( "ldap:///ou=system", url.toString() );
-            
+
         }
         catch ( LdapURLEncodingException luee )
         {
@@ -841,7 +838,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost/ou=system" );
-            
+
             assertEquals( "ldap://localhost/ou=system", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -850,7 +847,7 @@
         }
     }
 
-    
+
     /**
      * test a LdapURL with no host, a port, and a DN
      *
@@ -861,7 +858,7 @@
         try
         {
             new LdapURL( "ldap://:123/ou=system" );
-            
+
             fail();
         }
         catch ( LdapURLEncodingException luee )
@@ -870,7 +867,7 @@
         }
     }
 
-    
+
     /**
      * test a LdapURL with no DN
      *
@@ -881,7 +878,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -901,7 +898,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -921,7 +918,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -941,7 +938,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/???" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -949,8 +946,8 @@
             fail();
         }
     }
-    
-    
+
+
     /**
      * test a LdapURL with no DN and attributes
      *
@@ -961,7 +958,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -970,7 +967,7 @@
         }
     }
 
-    
+
     /**
      * test a LdapURL with a DN and attributes
      *
@@ -981,7 +978,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?ou,dc,cn" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?ou,dc,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1001,7 +998,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?ou,dc,cn" );
-            
+
             assertEquals( "ldap://localhost:123/?ou,dc,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1021,7 +1018,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??sub" );
-            
+
             assertEquals( "ldap://localhost:123/??sub", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1041,7 +1038,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??base" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1061,7 +1058,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1081,7 +1078,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??sub" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system??sub", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1101,7 +1098,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??base" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1121,7 +1118,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1141,7 +1138,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?ou,cn?sub" );
-            
+
             assertEquals( "ldap://localhost:123/?ou,cn?sub", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1161,7 +1158,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?ou,cn?base" );
-            
+
             assertEquals( "ldap://localhost:123/?ou,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1181,7 +1178,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?ou,cn?" );
-            
+
             assertEquals( "ldap://localhost:123/?ou,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1201,7 +1198,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?ou,cn?sub" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?ou,cn?sub", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1221,7 +1218,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?ou,cn?base" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?ou,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1241,7 +1238,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?ou,cn?" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?ou,cn", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1261,7 +1258,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/???(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/???(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1281,7 +1278,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system???(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system???(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1301,7 +1298,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,ou,dc??(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,ou,dc??(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1321,7 +1318,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??sub?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/??sub?(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1341,7 +1338,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??base?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/???(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1361,7 +1358,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,ou,dc?sub?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,ou,dc?sub?(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1381,7 +1378,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,ou,dc?base?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,ou,dc??(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1401,7 +1398,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??sub?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system??sub?(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1421,7 +1418,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??base?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system???(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1441,7 +1438,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,dc,ou??(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,dc,ou??(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1461,7 +1458,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?sub?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc?sub?(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1481,7 +1478,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?base?(cn=test)" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc??(cn=test)", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1501,7 +1498,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/????" );
-            
+
             assertEquals( "ldap://localhost:123/", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1521,7 +1518,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/????!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/????!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1541,7 +1538,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/???(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/???(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1561,7 +1558,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??sub??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/??sub??!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1581,7 +1578,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??base??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/????!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1601,7 +1598,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??sub?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/??sub?(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1621,7 +1618,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/??base?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/???(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1641,7 +1638,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou???!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou???!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1661,7 +1658,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou??(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou??(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1681,7 +1678,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou?sub??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou?sub??!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1701,7 +1698,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou?base??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou???!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1721,7 +1718,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou?sub?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou?sub?(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1741,7 +1738,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/?cn,dc,ou?base?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/?cn,dc,ou??(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1761,7 +1758,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system????!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system????!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1781,7 +1778,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system???(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system???(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1801,7 +1798,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??sub??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system??sub??!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1821,7 +1818,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??base??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system????!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1841,7 +1838,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??sub?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system??sub?(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1861,7 +1858,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system??base?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system???(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1881,7 +1878,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc???!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc???!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1901,7 +1898,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc??(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc??(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1921,7 +1918,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?sub??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc?sub??!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1941,7 +1938,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?base??!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc???!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1961,7 +1958,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?sub?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc?sub?(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1981,7 +1978,7 @@
         try
         {
             LdapURL url = new LdapURL( "ldap://localhost:123/ou=system?cn,ou,dc?base?(cn=test)?!a=b,!c" );
-            
+
             assertEquals( "ldap://localhost:123/ou=system?cn,ou,dc??(cn=test)?!a=b,!c", url.toString() );
         }
         catch ( LdapURLEncodingException luee )
@@ -1989,4 +1986,43 @@
             fail();
         }
     }
+
+
+    /**
+     * Test a LdapURL with an extension after an empty extension.
+     */
+    @Test
+    public void testLdapURLExtensionAfterEmptyExtension()
+    {
+        try
+        {
+            LdapURL url = new LdapURL( "ldap://localhost:123/????!a=b,!c,d=e" );
+
+            assertEquals( "ldap://localhost:123/????!a=b,!c,d=e", url.toString() );
+        }
+        catch ( LdapURLEncodingException luee )
+        {
+            fail();
+        }
+    }
+
+
+    /**
+     * Test the extension order of an LdapURL. 
+     */
+    @Test
+    public void testLdapURLExtensionOrder()
+    {
+        try
+        {
+            LdapURL url = new LdapURL( "ldap://localhost:123/????!a=b,!c,!x,d=e,f=g,!h=i" );
+
+            assertEquals( "ldap://localhost:123/????!a=b,!c,!x,d=e,f=g,!h=i", url.toString() );
+        }
+        catch ( LdapURLEncodingException luee )
+        {
+            fail();
+        }
+    }
+
 }