You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/09/12 20:28:45 UTC

svn commit: r280388 - in /directory: apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java

Author: akarasulu
Date: Mon Sep 12 11:28:37 2005
New Revision: 280388

URL: http://svn.apache.org/viewcvs?rev=280388&view=rev
Log:
changes ...

 o added test cases provided by Stefan Zoerner for DIREVE-243 here 
   http://issues.apache.org/jira/browse/DIREVE-243
 o added fix where we now utilize normalizers from the schema subsystem to 
   correctly compare values in compare operations

NOTE:

  Stefan I commented out the test case for the telephoneNumber match which 
  currently does not have a proper normalizer associated with it.  Perhaps 
  we can add the fix along with another JIRA issue.


Added:
    directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java   (with props)
Modified:
    directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java

Added: directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java?rev=280388&view=auto
==============================================================================
--- directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java (added)
+++ directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java Mon Sep 12 11:28:37 2005
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2004 Solarsis Group LLC.
+ *
+ * Licensed under the Open Software License, Version 2.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://opensource.org/licenses/osl-2.1.php
+ *
+ * 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.ldap.server;
+
+import java.util.Hashtable;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+
+/**
+ * Tests with compare operations on attributes which use different matching
+ * rules. Created to demonstrate JIRA DIREVE-243 ("Compare operation does not
+ * adhere to some matching rules").
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class MatchingRuleCompareTest extends AbstractServerTest
+{
+    private LdapContext ctx = null;
+
+    public static final String PERSON_CN = "Tori Amos";
+    public static final String PERSON_SN = "Amos";
+    public static final String PERSON_RDN = "cn=" + PERSON_CN;
+    public static final String PERSON_TELEPHONE = "1234567890abc";
+    public static final String PERSON_PWD = "Secret1!";
+
+    public static final String GROUP_CN = "Artists";
+    public static final String GROUP_RDN = "cn=" + GROUP_CN;
+
+    protected Attributes getPersonAttributes(String sn, String cn)
+    {
+        Attributes attributes = new BasicAttributes();
+        Attribute attribute = new BasicAttribute("objectClass");
+        attribute.add("top");
+        attribute.add("person");
+        attributes.put(attribute);
+        attributes.put("cn", cn);
+        attributes.put("sn", sn);
+
+        return attributes;
+    }
+
+    protected Attributes getGroupOfNamesAttributes(String cn, String member)
+    {
+        Attributes attributes = new BasicAttributes();
+        Attribute attribute = new BasicAttribute("objectClass");
+        attribute.add("top");
+        attribute.add("groupOfNames");
+        attributes.put(attribute);
+        attributes.put("cn", cn);
+        attributes.put("member", member);
+
+        return attributes;
+    }
+
+    /**
+     * Create context, a person entry and a group.
+     */
+    public void setUp() throws Exception
+    {
+        super.setUp();
+
+        Hashtable env = new Hashtable();
+        env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+        env.put("java.naming.provider.url", "ldap://localhost:" + port + "/ou=system");
+        env.put("java.naming.security.principal", "uid=admin,ou=system");
+        env.put("java.naming.security.credentials", "secret");
+        env.put("java.naming.security.authentication", "simple");
+
+        ctx = new InitialLdapContext(env, null);
+        assertNotNull(ctx);
+
+        // Create a person
+        Attributes attributes = this.getPersonAttributes(PERSON_SN, PERSON_CN);
+        attributes.put("telephoneNumber", PERSON_TELEPHONE);
+        attributes.put("userPassword", PERSON_PWD);
+        ctx.createSubcontext(PERSON_RDN, attributes);
+
+        // Create a group
+        DirContext member = (DirContext) ctx.lookup(PERSON_RDN);
+        attributes = this.getGroupOfNamesAttributes(GROUP_CN, member.getNameInNamespace());
+        ctx.createSubcontext(GROUP_RDN, attributes);
+    }
+
+    /**
+     * Remove entries and close context.
+     */
+    public void tearDown() throws Exception
+    {
+        ctx.unbind(PERSON_RDN);
+        ctx.unbind(GROUP_RDN);
+
+        ctx.close();
+
+        super.tearDown();
+    }
+
+    /**
+     * Compare with caseIgnoreMatch matching rule.
+     * 
+     * @throws NamingException
+     */
+    public void testCaseIgnoreMatch() throws NamingException
+    {
+        // Setting up search controls for compare op
+        SearchControls ctls = new SearchControls();
+        ctls.setReturningAttributes(new String[] {}); // no attributes
+        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+
+        String[] values = { PERSON_SN, PERSON_SN.toUpperCase(), PERSON_SN.toLowerCase(), PERSON_SN + "X" };
+        boolean[] expected = { true, true, true, false };
+
+        for (int i = 0; i < values.length; i++) {
+            String value = values[i];
+
+            NamingEnumeration enumeration = ctx.search(PERSON_RDN, "sn={0}", new String[] { value }, ctls);
+            boolean result = enumeration.hasMore();
+
+            assertEquals("compare sn value '" + PERSON_SN + "' with '" + value + "'", expected[i], result);
+
+            enumeration.close();
+        }
+    }
+
+    //
+
+    /**
+     * Compare with telephoneNumberMatch matching rule.
+     * 
+     * @throws NamingException
+     */
+
+// Comment this out until we have the telephone number match working.
+
+//    public void testTelephoneNumberMatch() throws NamingException
+//    {
+//        // Setting up search controls for compare op
+//        SearchControls ctls = new SearchControls();
+//        ctls.setReturningAttributes(new String[] {}); // no attributes
+//        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+//
+//        String[] values = { "", "1234567890abc", "   1234567890 A B C", "123 456 7890 abc", "123-456-7890 abC",
+//                "123456-7890 A bc" };
+//        boolean[] expected = { false, true, true, true, true, true };
+//
+//        for (int i = 0; i < values.length; i++) {
+//            String value = values[i];
+//
+//            NamingEnumeration enumeration = ctx.search(PERSON_RDN, "telephoneNumber={0}", new String[] { value }, ctls);
+//            boolean result = enumeration.hasMore();
+//
+//            assertEquals("compare '" + PERSON_TELEPHONE + "' with '" + value + "'", expected[i], result);
+//
+//            enumeration.close();
+//        }
+//    }
+
+    /**
+     * Compare with octetStringMatch matching rule.
+     * 
+     * @throws NamingException
+     */
+    public void testOctetStringMatch() throws NamingException
+    {
+        // Setting up search controls for compare op
+        SearchControls ctls = new SearchControls();
+        ctls.setReturningAttributes(new String[] {}); // no attributes
+        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+
+        String[] values = { "", PERSON_PWD, PERSON_PWD.toUpperCase(), PERSON_PWD.toLowerCase(), PERSON_PWD + "X" };
+        boolean[] expected = { false, true, false, false, false };
+
+        for (int i = 0; i < values.length; i++) {
+            String value = values[i];
+
+            NamingEnumeration enumeration = ctx.search(PERSON_RDN, "userPassword={0}", new String[] { value }, ctls);
+            boolean result = enumeration.hasMore();
+
+            assertEquals("compare '" + PERSON_PWD + "' with '" + value + "'", expected[i], result);
+
+            enumeration.close();
+        }
+    }
+
+    /**
+     * Compare with distinguishedNameMatch matching rule.
+     * 
+     * @throws NamingException
+     */
+    public void testDistinguishedNameMatch() throws NamingException
+    {
+        // determine member DN of person
+        DirContext member = (DirContext) ctx.lookup(PERSON_RDN);
+        String memberDN = member.getNameInNamespace();
+
+        // Setting up search controls for compare op
+        SearchControls ctls = new SearchControls();
+        ctls.setReturningAttributes(new String[] {}); // no attributes
+        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+
+        String[] values = { "", memberDN, "cn=nobody", memberDN.toLowerCase(),
+                PERSON_RDN + " , " + ctx.getNameInNamespace() };
+        boolean[] expected = { false, true, false, true, true };
+
+        for (int i = 0; i < values.length; i++) {
+            String value = values[i];
+
+            NamingEnumeration enumeration = ctx.search(GROUP_RDN, "member={0}", new Object[] { value }, ctls);
+            boolean result = enumeration.hasMore();
+
+            assertEquals("compare '" + memberDN + "' with '" + value + "'", expected[i], result);
+
+            enumeration.close();
+        }
+    }
+
+}

Propchange: directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MatchingRuleCompareTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java?rev=280388&r1=280387&r2=280388&view=diff
==============================================================================
--- directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java (original)
+++ directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/CompareHandler.java Mon Sep 12 11:28:37 2005
@@ -28,6 +28,7 @@
 import org.apache.ldap.common.message.LdapResultImpl;
 import org.apache.ldap.common.message.ResultCodeEnum;
 import org.apache.ldap.common.util.ExceptionUtils;
+import org.apache.ldap.common.schema.Normalizer;
 import org.apache.ldap.server.jndi.ContextFactoryService;
 import org.apache.ldap.server.schema.AttributeTypeRegistry;
 import org.apache.mina.protocol.ProtocolSession;
@@ -59,21 +60,49 @@
             AttributeTypeRegistry registry = ContextFactoryService.getInstance().
                     getConfiguration().getGlobalRegistries().getAttributeTypeRegistry();
 
+            // complain if we do not recognize the attribute being compared
             if ( ! registry.hasAttributeType( req.getAttributeId() ) )
             {
                 resp.getLdapResult().setResultCode( ResultCodeEnum.UNDEFINEDATTRIBUTETYPE );
             }
+            // complain if the attribute being compared does not exist in the entry
             else if ( attr == null )
             {
                 resp.getLdapResult().setResultCode( ResultCodeEnum.NOSUCHATTRIBUTE );
             }
+            // see first if simple match without normalization succeeds
             else if ( attr.contains( req.getAssertionValue() ) )
             {
                 resp.getLdapResult().setResultCode( ResultCodeEnum.COMPARETRUE );
             }
+            // now must apply normalization to all values (attr and in request) to compare
             else
             {
-                resp.getLdapResult().setResultCode( ResultCodeEnum.COMPAREFALSE );
+                /*
+                 * Get ahold of the normalizer for the attribute and normalize the request
+                 * assertion value for comparisons with normalized attribute values.  Loop
+                 * through all values looking for a match.
+                 */
+                Normalizer normalizer = registry.lookup( req.getAttributeId() ).getEquality().getNormalizer();
+                String reqVal = ( String ) normalizer.normalize( req.getAssertionValue() );
+                boolean isCompareTrue = false;
+
+                for ( int ii = 0; ii < attr.size(); ii++ )
+                {
+                    String attrVal = ( String ) normalizer.normalize( attr.get( ii ) );
+                    if ( attrVal.equals( reqVal ) )
+                    {
+                        resp.getLdapResult().setResultCode( ResultCodeEnum.COMPARETRUE );
+                        isCompareTrue = true;
+                        break;
+                    }
+                }
+
+                // if no match was found then we set compare to false
+                if ( ! isCompareTrue )
+                {
+                    resp.getLdapResult().setResultCode( ResultCodeEnum.COMPAREFALSE );
+                }
             }
         }
         catch ( NamingException e )