1   /*
2    * Copyright (c) 2004 Solarsis Group LLC.
3    *
4    * Licensed under the Open Software License, Version 2.1 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://opensource.org/licenses/osl-2.1.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.ldap.server;
17  
18  import java.util.Hashtable;
19  
20  import javax.naming.NamingException;
21  import javax.naming.directory.Attribute;
22  import javax.naming.directory.AttributeInUseException;
23  import javax.naming.directory.Attributes;
24  import javax.naming.directory.BasicAttribute;
25  import javax.naming.directory.BasicAttributes;
26  import javax.naming.directory.DirContext;
27  import javax.naming.ldap.InitialLdapContext;
28  import javax.naming.ldap.LdapContext;
29  
30  /***
31   * Testcase with different modify operations on a person entry. Each includes a
32   * single add op only. Created to demonstrate DIREVE-241 ("Adding an already
33   * existing attribute value with a modify operation does not cause an error.").
34   * 
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   * @version $Rev$
37   */
38  public class ModifyAddTest extends AbstractServerTest
39  {
40      private LdapContext ctx = null;
41  
42      public static final String RDN = "cn=Tori Amos";
43  
44      public static final String PERSON_DESCRIPTION = "an American singer-songwriter";
45  
46      /***
47       * Creation of required attributes of a person entry.
48       */
49      protected Attributes getPersonAttributes(String sn, String cn)
50      {
51          Attributes attributes = new BasicAttributes();
52          Attribute attribute = new BasicAttribute("objectClass");
53          attribute.add("top");
54          attribute.add("person");
55          attributes.put(attribute);
56          attributes.put("cn", cn);
57          attributes.put("sn", sn);
58  
59          return attributes;
60      }
61  
62      /***
63       * Create context and a person entry.
64       */
65      public void setUp() throws Exception
66      {
67          super.setUp();
68  
69          Hashtable env = new Hashtable();
70          env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
71          env.put("java.naming.provider.url", "ldap://localhost:" + port + "/ou=system");
72          env.put("java.naming.security.principal", "uid=admin,ou=system");
73          env.put("java.naming.security.credentials", "secret");
74          env.put("java.naming.security.authentication", "simple");
75  
76          ctx = new InitialLdapContext(env, null);
77          assertNotNull(ctx);
78  
79          // Create a person with description
80          Attributes attributes = this.getPersonAttributes("Amos", "Tori Amos");
81          attributes.put("description", "an American singer-songwriter");
82          ctx.createSubcontext(RDN, attributes);
83  
84      }
85  
86      /***
87       * Remove person entry and close context.
88       */
89      public void tearDown() throws Exception
90      {
91          ctx.unbind(RDN);
92          ctx.close();
93  
94          ctx.close();
95          ctx = null;
96  
97          super.tearDown();
98      }
99  
100     /***
101      * Add a new attribute to a person entry.
102      * 
103      * @throws NamingException
104      */
105     public void testAddNewAttributeValue() throws NamingException
106     {
107 
108         // Add telephoneNumber attribute
109         String newValue = "1234567890";
110         Attributes attrs = new BasicAttributes("telephoneNumber", newValue);
111         ctx.modifyAttributes(RDN, DirContext.ADD_ATTRIBUTE, attrs);
112 
113         // Verify, that attribute value is added
114         attrs = ctx.getAttributes(RDN);
115         Attribute attr = attrs.get("telephoneNumber");
116         assertNotNull(attr);
117         assertTrue(attr.contains(newValue));
118         assertEquals(1, attr.size());
119     }
120 
121     /***
122      * Add a new attribute with two values.
123      * 
124      * @throws NamingException
125      */
126     public void testAddNewAttributeValues() throws NamingException
127     {
128 
129         // Add telephoneNumber attribute
130         String[] newValues = { "1234567890", "999999999" };
131         Attribute attr = new BasicAttribute("telephoneNumber");
132         attr.add(newValues[0]);
133         attr.add(newValues[1]);
134         Attributes attrs = new BasicAttributes();
135         attrs.put(attr);
136         ctx.modifyAttributes(RDN, DirContext.ADD_ATTRIBUTE, attrs);
137 
138         // Verify, that attribute values are present
139         attrs = ctx.getAttributes(RDN);
140         attr = attrs.get("telephoneNumber");
141         assertNotNull(attr);
142         assertTrue(attr.contains(newValues[0]));
143         assertTrue(attr.contains(newValues[1]));
144         assertEquals(newValues.length, attr.size());
145     }
146 
147     /***
148      * Add an additional value.
149      * 
150      * @throws NamingException
151      */
152     public void testAddAdditionalAttributeValue() throws NamingException
153     {
154 
155         // A new description attribute value
156         String newValue = "A new description for this person";
157         assertFalse(newValue.equals(PERSON_DESCRIPTION));
158         Attributes attrs = new BasicAttributes("description", newValue);
159 
160         ctx.modifyAttributes(RDN, DirContext.ADD_ATTRIBUTE, attrs);
161 
162         // Verify, that attribute value is added
163         attrs = ctx.getAttributes(RDN);
164         Attribute attr = attrs.get("description");
165         assertNotNull(attr);
166         assertTrue(attr.contains(newValue));
167         assertTrue(attr.contains(PERSON_DESCRIPTION));
168         assertEquals(2, attr.size());
169     }
170 
171     /***
172      * Try to add an already existing attribute value.
173      * 
174      * Expected behaviour: Modify operation fails with an
175      * AttributeInUseException. Original LDAP Error code: 20 (Indicates that the
176      * attribute value specified in a modify or add operation already exists as
177      * a value for that attribute).
178      * 
179      * @throws NamingException
180      */
181     public void testAddExistingAttributeValue() throws NamingException
182     {
183 
184         // Change description attribute
185         Attributes attrs = new BasicAttributes("description", PERSON_DESCRIPTION);
186         try
187         {
188             ctx.modifyAttributes(RDN, DirContext.ADD_ATTRIBUTE, attrs);
189             fail("Adding an already existing atribute value should fail.");
190         }
191         catch (AttributeInUseException e)
192         {
193             // expected behaviour
194         }
195 
196         // Verify, that attribute is still there, and is the only one
197         attrs = ctx.getAttributes(RDN);
198         Attribute attr = attrs.get("description");
199         assertNotNull(attr);
200         assertTrue(attr.contains(PERSON_DESCRIPTION));
201         assertEquals(1, attr.size());
202     }
203 }