1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  package org.apache.directory.server.operations.modifydn;
21  
22  
23  import javax.naming.ReferralException;
24  import javax.naming.ldap.LdapContext;
25  
26  import netscape.ldap.LDAPConnection;
27  import netscape.ldap.LDAPConstraints;
28  import netscape.ldap.LDAPControl;
29  import netscape.ldap.LDAPEntry;
30  import netscape.ldap.LDAPException;
31  import netscape.ldap.LDAPResponse;
32  import netscape.ldap.LDAPResponseListener;
33  import netscape.ldap.LDAPSearchConstraints;
34  
35  import org.apache.directory.server.core.integ.Level;
36  import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
37  import org.apache.directory.server.core.integ.annotations.CleanupLevel;
38  import org.apache.directory.server.integ.SiRunner;
39  import org.apache.directory.server.ldap.LdapService;
40  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
41  import org.junit.Test;
42  import org.junit.runner.RunWith;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredConnection;
47  import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContextThrowOnRefferal;
48  import static org.junit.Assert.assertEquals;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.fail;
51  
52  
53  /**
54   * Tests the server to make sure standard compare operations work properly.
55   *
56   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
57   * @version $Rev$, $Date$
58   */
59  @RunWith ( SiRunner.class ) 
60  @CleanupLevel ( Level.SUITE )
61  @ApplyLdifs( {
62      // Entry # 1
63      "dn: uid=akarasulu,ou=users,ou=system\n" +
64      "objectClass: uidObject\n" +
65      "objectClass: person\n" +
66      "objectClass: top\n" +
67      "uid: akarasulu\n" +
68      "cn: Alex Karasulu\n" +
69      "sn: karasulu\n\n" + 
70      // Entry # 2
71      "dn: ou=Computers,uid=akarasulu,ou=users,ou=system\n" +
72      "objectClass: organizationalUnit\n" +
73      "objectClass: top\n" +
74      "ou: computers\n" +
75      "description: Computers for Alex\n" +
76      "seeAlso: ou=Machines,uid=akarasulu,ou=users,ou=system\n\n" + 
77      // Entry # 3
78      "dn: uid=akarasuluref,ou=users,ou=system\n" +
79      "objectClass: uidObject\n" +
80      "objectClass: referral\n" +
81      "objectClass: top\n" +
82      "uid: akarasuluref\n" +
83      "ref: ldap://localhost:10389/uid=akarasulu,ou=users,ou=system\n" + 
84      "ref: ldap://foo:10389/uid=akarasulu,ou=users,ou=system\n" +
85      "ref: ldap://bar:10389/uid=akarasulu,ou=users,ou=system\n\n" +
86      // Entry # 4
87      "dn: uid=elecharny,ou=users,ou=system\n" +
88      "objectClass: uidObject\n" +
89      "objectClass: person\n" +
90      "objectClass: top\n" +
91      "uid: elecharny\n" +
92      "cn: Emmanuel Lecharny\n" +
93      "sn: lecharny\n\n"
94      }
95  )
96  public class ModifyDnReferralIT
97  {
98      private static final Logger LOG = LoggerFactory.getLogger( ModifyDnReferralIT.class );
99      
100     public static LdapService ldapService;
101     
102 
103     /**
104      * Tests ModifyDN operation on referral entry with the ManageDsaIT control.
105      */
106     @Test
107     public void testOnReferralWithManageDsaITControl() throws Exception
108     {
109         LDAPConnection conn = getWiredConnection( ldapService );
110         LDAPConstraints constraints = new LDAPSearchConstraints();
111         constraints.setClientControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
112         constraints.setServerControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
113         conn.setConstraints( constraints );
114         
115         // ModifyDN success
116         conn.rename( "uid=akarasuluref,ou=users,ou=system", "uid=ref", true, constraints );
117         LDAPEntry entry = conn.read( "uid=ref,ou=users,ou=system", ( LDAPSearchConstraints ) constraints );
118         assertNotNull( entry );
119         assertEquals( "uid=ref,ou=users,ou=system", entry.getDN() );
120         
121         conn.disconnect();
122     }
123     
124     
125     /**
126      * Tests ModifyDN operation with newSuperior on referral entry with the 
127      * ManageDsaIT control.
128      */
129     @Test
130     public void testNewSuperiorOnReferralWithManageDsaITControl() throws Exception
131     {
132         LDAPConnection conn = getWiredConnection( ldapService );
133         LDAPConstraints constraints = new LDAPSearchConstraints();
134         constraints.setClientControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
135         constraints.setServerControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
136         conn.setConstraints( constraints );
137         
138         // ModifyDN success
139         conn.rename( "uid=elecharny,ou=users,ou=system", "uid=newuser", 
140             "uid=akarasuluref,ou=users,ou=system", true, constraints );
141         LDAPEntry entry = conn.read( "uid=newuser,uid=akarasuluref,ou=users,ou=system", 
142             ( LDAPSearchConstraints ) constraints );
143         assertNotNull( entry );
144         assertEquals( "uid=newuser,uid=akarasuluref,ou=users,ou=system", entry.getDN() );
145         
146         conn.disconnect();
147     }
148     
149     
150     /**
151      * Tests ModifyDN operation on normal and referral entries without the 
152      * ManageDsaIT control. Referrals are sent back to the client with a
153      * non-success result code.
154      */
155     @Test
156     public void testOnReferral() throws Exception
157     {
158         LDAPConnection conn = getWiredConnection( ldapService );
159         LDAPConstraints constraints = new LDAPConstraints();
160         constraints.setReferrals( false );
161         conn.setConstraints( constraints );
162         
163         // referrals failure
164         LDAPResponseListener listener = null;
165         LDAPResponse response = null;
166 
167         listener = conn.rename( "uid=akarasuluref,ou=users,ou=system", "uid=ref", true, null, constraints );
168         response = listener.getResponse();
169         assertEquals( ResultCodeEnum.REFERRAL.getValue(), response.getResultCode() );
170 
171         assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[0] );
172         assertEquals( "ldap://foo:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[1] );
173         assertEquals( "ldap://bar:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[2] );
174 
175         conn.disconnect();
176     }
177     
178     
179     /**
180      * Tests ModifyDN operation on normal and referral entries without the 
181      * ManageDsaIT control. Referrals are sent back to the client with a
182      * non-success result code.
183      */
184     @Test
185     public void testNewSupierorOnReferral() throws Exception
186     {
187         LDAPConnection conn = getWiredConnection( ldapService );
188         LDAPConstraints constraints = new LDAPConstraints();
189         constraints.setReferrals( false );
190         conn.setConstraints( constraints );
191         
192         // referrals failure
193         try
194         {
195             conn.rename( "uid=elecharny,ou=users,ou=system", "uid=ref", 
196                 "uid=akarasuluref,ou=users,ou=system", true, constraints );
197         }
198         catch ( LDAPException e )
199         {
200             assertEquals( LDAPException.AFFECTS_MULTIPLE_DSAS, e.getLDAPResultCode() );
201         }
202 
203         conn.disconnect();
204     }
205     
206     
207     /**
208      * Tests ModifyDN operation on normal and referral entries without the 
209      * ManageDsaIT control using JNDI instead of the Netscape API. Referrals 
210      * are sent back to the client with a non-success result code.
211      */
212     @Test
213     public void testThrowOnReferralWithJndi() throws Exception
214     {
215         LdapContext ctx = getWiredContextThrowOnRefferal( ldapService );
216         
217         // ModifyDN referrals failure
218         try
219         {
220             ctx.rename( "uid=akarasuluref,ou=users,ou=system", "uid=ref,ou=users,ou=system" ); 
221             fail( "Should never get here due to ModifyDN failure on ReferralException" );
222         }
223         catch ( ReferralException e )
224         {
225             // seems JNDI only returns the first referral URL and not all so we test for it
226             assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", e.getReferralInfo() );
227         }
228 
229         ctx.close();
230     }
231     
232     
233     /**
234      * Tests referral handling when an ancestor is a referral.
235      */
236     @Test 
237     public void testAncestorReferral() throws Exception
238     {
239         LOG.debug( "" );
240 
241         LDAPConnection conn = getWiredConnection( ldapService );
242         LDAPConstraints constraints = new LDAPConstraints();
243         conn.setConstraints( constraints );
244 
245         // referrals failure
246         LDAPResponseListener listener = null;
247         LDAPResponse response = null;
248 
249         listener = conn.rename( "ou=Computers,uid=akarasuluref,ou=users,ou=system", "ou=Machines", true, null, constraints );
250         response = listener.getResponse();
251         assertEquals( ResultCodeEnum.REFERRAL.getValue(), response.getResultCode() );
252 
253         assertEquals( "ldap://localhost:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[0] );
254         assertEquals( "ldap://foo:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[1] );
255         assertEquals( "ldap://bar:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[2] );
256 
257         conn.disconnect();
258     }
259     
260     
261     /**
262      * Tests referral handling when an ancestor is a referral.
263      */
264     @Test 
265     public void testNewSuperiorAncestorReferral() throws Exception
266     {
267         LOG.debug( "" );
268 
269         LDAPConnection conn = getWiredConnection( ldapService );
270         LDAPConstraints constraints = new LDAPConstraints();
271         conn.setConstraints( constraints );
272 
273         // referrals failure
274         try
275         {
276             conn.rename( "uid=elecharny,ou=users,ou=system", "ou=Machines", 
277                 "ou=Computers,uid=akarasuluref,ou=users,ou=system", true, constraints );
278             fail( "Should never get here to affectsMultipleDSA error result code" );
279         }
280         catch ( LDAPException e )
281         {
282             assertEquals( LDAPException.AFFECTS_MULTIPLE_DSAS, e.getLDAPResultCode() );
283         }
284 
285         conn.disconnect();
286     }
287 }