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.Attributes;
23  import javax.naming.directory.BasicAttribute;
24  import javax.naming.directory.BasicAttributes;
25  import javax.naming.directory.DirContext;
26  import javax.naming.directory.InvalidAttributeIdentifierException;
27  import javax.naming.directory.NoSuchAttributeException;
28  import javax.naming.directory.SchemaViolationException;
29  import javax.naming.ldap.InitialLdapContext;
30  import javax.naming.ldap.LdapContext;
31  
32  import junit.framework.TestCase;
33  
34  /***
35   * Testcase with different modify operations on a person entry. Each includes a
36   * single removal op only.
37   * 
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   * @version $Rev$
40   */
41  public class ModifyRemoveTest extends AbstractServerTest
42  {
43  
44      private LdapContext ctx = null;
45  
46      public static final String RDN = "cn=Tori Amos";
47  
48      /***
49       * Creation of required attributes of a person entry.
50       */
51      protected Attributes getPersonAttributes(String sn, String cn)
52      {
53          Attributes attributes = new BasicAttributes();
54          Attribute attribute = new BasicAttribute("objectClass");
55          attribute.add("top");
56          attribute.add("person");
57          attributes.put(attribute);
58          attributes.put("cn", cn);
59          attributes.put("sn", sn);
60  
61          return attributes;
62      }
63  
64      /***
65       * Create context and a person entry.
66       */
67      public void setUp() throws Exception
68      {
69          super.setUp();
70  
71          Hashtable env = new Hashtable();
72          env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
73          env.put("java.naming.provider.url", "ldap://localhost:" + port + "/ou=system");
74          env.put("java.naming.security.principal", "uid=admin,ou=system");
75          env.put("java.naming.security.credentials", "secret");
76          env.put("java.naming.security.authentication", "simple");
77  
78          ctx = new InitialLdapContext(env, null);
79          assertNotNull(ctx);
80  
81          // Create a person with description
82          Attributes attributes = this.getPersonAttributes("Amos", "Tori Amos");
83          attributes.put("description", "an American singer-songwriter");
84          ctx.createSubcontext(RDN, attributes);
85  
86      }
87  
88      /***
89       * Remove person entry and close context.
90       */
91      public void tearDown() throws Exception
92      {
93          ctx.unbind(RDN);
94          ctx.close();
95  
96          ctx.close();
97          ctx = null;
98  
99          super.tearDown();
100     }
101 
102     /***
103      * Just a little test to check wether opening the connection and creation of
104      * the person succeeds succeeds.
105      */
106     public void testSetUpTearDown() throws NamingException
107     {
108         assertNotNull(ctx);
109         DirContext tori = (DirContext) ctx.lookup(RDN);
110         assertNotNull(tori);
111     }
112 
113     /***
114      * Remove an attribute, which is not required.
115      * 
116      * Expected result: After successful deletion, attribute is not present in
117      * entry.
118      * 
119      * @throws NamingException
120      */
121     public void testRemoveNotRequiredAttribute() throws NamingException
122     {
123         // Remove description Attribute
124         Attribute attr = new BasicAttribute("description");
125         Attributes attrs = new BasicAttributes();
126         attrs.put(attr);
127         ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
128 
129         // Verify, that attribute is deleted
130         attrs = ctx.getAttributes(RDN);
131         attr = attrs.get("description");
132         assertNull(attr);
133     }
134 
135     /***
136      * Remove two not required attributes.
137      * 
138      * Expected result: After successful deletion, both attributes ar not
139      * present in entry.
140      * 
141      * @throws NamingException
142      */
143     public void testRemoveTwoNotRequiredAttributes() throws NamingException
144     {
145 
146         // add telephoneNumber to entry
147         Attributes tn = new BasicAttributes("telephoneNumber", "12345678");
148         ctx.modifyAttributes(RDN, DirContext.ADD_ATTRIBUTE, tn);
149 
150         // Remove description and telephoneNumber to Attribute
151         Attributes attrs = new BasicAttributes();
152         attrs.put(new BasicAttribute("description"));
153         attrs.put(new BasicAttribute("telephoneNumber"));
154         ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
155 
156         // Verify, that attributes are deleted
157         attrs = ctx.getAttributes(RDN);
158         assertNull(attrs.get("description"));
159         assertNull(attrs.get("telephoneNumber"));
160         assertNotNull(attrs.get("cn"));
161         assertNotNull(attrs.get("sn"));
162     }
163 
164     /***
165      * Remove a required attribute. The sn attribute of the person entry is used
166      * here.
167      * 
168      * Expected Result: Deletion fails with NamingException (Schema Violation).
169      * 
170      * @throws NamingException
171      */
172     public void testRemoveRequiredAttribute() throws NamingException
173     {
174 
175         // Remove sn attribute
176         Attribute attr = new BasicAttribute("sn");
177         Attributes attrs = new BasicAttributes();
178         attrs.put(attr);
179 
180         try {
181             ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
182             fail("Deletion of required attribute should fail.");
183         } catch (SchemaViolationException e) {
184             // expected behaviour
185         }
186     }
187 
188     /***
189      * Remove a required attribute from RDN.
190      * 
191      * Expected Result: Deletion fails with SchemaViolationException.
192      * 
193      * @throws NamingException
194      */
195     public void testRemovePartOfRdn() throws NamingException
196     {
197 
198         // Remove sn attribute
199         Attribute attr = new BasicAttribute("cn");
200         Attributes attrs = new BasicAttributes();
201         attrs.put(attr);
202 
203         try {
204             ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
205             fail("Deletion of RDN attribute should fail.");
206         } catch (SchemaViolationException e) {
207             // expected behaviour
208         }
209     }
210 
211     /***
212      * Remove a not required attribute from RDN.
213      * 
214      * Expected Result: Deletion fails with SchemaViolationException.
215      * 
216      * @throws NamingException
217      */
218     public void testRemovePartOfRdnNotRequired() throws NamingException
219     {
220 
221         // Change RDN to another attribute
222         String newRdn = "description=an American singer-songwriter";
223         ctx.addToEnvironment("java.naming.ldap.deleteRDN", "false");
224         ctx.rename(RDN, newRdn);
225 
226         // Remove description, which is now RDN attribute
227         Attribute attr = new BasicAttribute("description");
228         Attributes attrs = new BasicAttributes();
229         attrs.put(attr);
230 
231         try {
232             ctx.modifyAttributes(newRdn, DirContext.REMOVE_ATTRIBUTE, attrs);
233             fail("Deletion of RDN attribute should fail.");
234         } catch (SchemaViolationException e) {
235             // expected behaviour
236         }
237 
238         // Change RDN back to original
239         ctx.addToEnvironment("java.naming.ldap.deleteRDN", "false");
240         ctx.rename(newRdn, RDN);
241     }
242 
243     /***
244      * Remove a an attribute which is not present on the entry, but in the
245      * schema.
246      * 
247      * Expected result: Deletion fails with NoSuchAttributeException
248      * 
249      * @throws NamingException
250      */
251     public void testRemoveAttributeNotPresent() throws NamingException
252     {
253 
254         // Remove telephoneNumber Attribute
255         Attribute attr = new BasicAttribute("telephoneNumber");
256         Attributes attrs = new BasicAttributes();
257         attrs.put(attr);
258 
259         try {
260             ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
261             fail("Deletion of attribute, which is not present in the entry, should fail.");
262         } catch (NoSuchAttributeException e) {
263             // expected behaviour
264         }
265     }
266 
267     /***
268      * Remove a an attribute which is not present in the schema.
269      * 
270      * Expected result: Deletion fails with NoSuchAttributeException
271      * 
272      * @throws NamingException
273      */
274     public void testRemoveAttributeNotValid() throws NamingException
275     {
276 
277         // Remove phantasy attribute
278         Attribute attr = new BasicAttribute("XXX");
279         Attributes attrs = new BasicAttributes();
280         attrs.put(attr);
281 
282         try {
283             ctx.modifyAttributes(RDN, DirContext.REMOVE_ATTRIBUTE, attrs);
284             fail("Deletion of an invalid attribute should fail.");
285         } catch (NoSuchAttributeException e) {
286             // expected behaviour
287         } catch (InvalidAttributeIdentifierException e) {
288             // expected behaviour
289         }
290     }
291 
292 }