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.core.jndi;
21  
22  
23  import org.apache.directory.server.core.DefaultDirectoryService;
24  import org.apache.directory.server.core.DirectoryService;
25  import org.apache.directory.server.core.entry.ServerEntry;
26  import org.apache.directory.server.core.integ.CiRunner;
27  import org.apache.directory.server.core.integ.DirectoryServiceFactory;
28  import static org.apache.directory.server.core.integ.IntegrationUtils.getSchemaContext;
29  import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
30  import org.apache.directory.server.core.integ.Level;
31  import org.apache.directory.server.core.integ.annotations.Factory;
32  import org.apache.directory.server.core.integ.annotations.CleanupLevel;
33  import org.apache.directory.server.xdbm.Index;
34  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
35  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
36  
37  import static org.junit.Assert.assertFalse;
38  import static org.junit.Assert.assertTrue;
39  import org.junit.Test;
40  import org.junit.runner.RunWith;
41  
42  import javax.naming.NamingEnumeration;
43  import javax.naming.NamingException;
44  import javax.naming.directory.Attribute;
45  import javax.naming.directory.Attributes;
46  import javax.naming.directory.BasicAttribute;
47  import javax.naming.directory.BasicAttributes;
48  import javax.naming.directory.DirContext;
49  import javax.naming.directory.ModificationItem;
50  import javax.naming.directory.SearchControls;
51  import javax.naming.directory.SearchResult;
52  import javax.naming.ldap.LdapContext;
53  import java.util.HashSet;
54  import java.util.Set;
55  
56  
57  /**
58   * Tests various search scenarios.
59   *
60   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
61   * @version $Rev$
62   */
63  @RunWith ( CiRunner.class )
64  @CleanupLevel ( Level.CLASS )
65  @Factory ( SearchWithIndicesITest.MyFactory.class )
66  public class SearchWithIndicesITest
67  {
68      public static DirectoryService service;
69  
70  
71  
72      private void createData() throws Exception
73      {
74          // -------------------------------------------------------------------
75          // Enable the nis schema
76          // -------------------------------------------------------------------
77  
78          // check if nis is disabled
79          LdapContext schemaRoot = getSchemaContext( service );
80          Attributes nisAttrs = schemaRoot.getAttributes( "cn=nis" );
81          boolean isNisDisabled = false;
82          if ( nisAttrs.get( "m-disabled" ) != null )
83          {
84              isNisDisabled = ( ( String ) nisAttrs.get( "m-disabled" ).get() ).equalsIgnoreCase( "TRUE" );
85          }
86  
87          // if nis is disabled then enable it
88          if ( isNisDisabled )
89          {
90              Attribute disabled = new BasicAttribute( "m-disabled" );
91              ModificationItem[] mods = new ModificationItem[] {
92                  new ModificationItem( DirContext.REMOVE_ATTRIBUTE, disabled ) };
93              schemaRoot.modifyAttributes( "cn=nis", mods );
94          }
95  
96          // -------------------------------------------------------------------
97          // Add a bunch of nis groups
98          // -------------------------------------------------------------------
99  
100         addNisPosixGroup( "testGroup0", 0 );
101         addNisPosixGroup( "testGroup1", 1 );
102         addNisPosixGroup( "testGroup2", 2 );
103         addNisPosixGroup( "testGroup4", 4 );
104         addNisPosixGroup( "testGroup5", 5 );
105     }
106 
107 
108     private DirContext addNisPosixGroup( String name, int gid ) throws Exception
109     {
110         Attributes attrs = new BasicAttributes( "objectClass", "top", true );
111         attrs.get( "objectClass" ).add( "posixGroup" );
112         attrs.put( "cn", name );
113         attrs.put( "gidNumber", String.valueOf( gid ) );
114         return getSystemContext( service ).createSubcontext( "cn="+name+",ou=groups", attrs );
115     }
116     
117     
118     public static class MyFactory implements DirectoryServiceFactory
119     {
120         public DirectoryService newInstance() 
121         {
122             DirectoryService service = new DefaultDirectoryService();
123             service.getChangeLog().setEnabled( true );
124 
125             // -------------------------------------------------------------------
126             // Alter the partition configuration to index gidNumber
127             // -------------------------------------------------------------------
128 
129             JdbmPartition partition = new JdbmPartition();
130             partition.setId( "system" );
131             partition.setSuffix( "ou=system" );
132 
133             Set<Index<?, ServerEntry>> indices = new HashSet<Index<?, ServerEntry>>();
134             indices.addAll( partition.getIndexedAttributes() );
135             indices.add( new JdbmIndex<String,ServerEntry>( "gidNumber" ) );
136             partition.setIndexedAttributes( indices );
137             service.setSystemPartition( partition );
138 
139             return service;
140         }
141     }
142     
143     
144     /**
145      *  Convenience method that performs a one level search using the
146      *  specified filter returning their DNs as Strings in a set.
147      *
148      * @param controls the search controls
149      * @param filter the filter expression
150      * @return the set of groups
151      * @throws NamingException if there are problems conducting the search
152      */
153     public Set<String> searchGroups( String filter, SearchControls controls ) throws Exception
154     {
155         if ( controls == null )
156         {
157             controls = new SearchControls();
158         }
159 
160         Set<String> results = new HashSet<String>();
161         NamingEnumeration<SearchResult> list = getSystemContext( service ).search( "ou=groups", filter, controls );
162 
163         while( list.hasMore() )
164         {
165             SearchResult result = list.next();
166             results.add( result.getName() );
167         }
168 
169         return results;
170     }
171 
172 
173     /**
174      *  Convenience method that performs a one level search using the
175      *  specified filter returning their DNs as Strings in a set.
176      *
177      * @param filter the filter expression
178      * @return the set of group names
179      * @throws NamingException if there are problems conducting the search
180      */
181     public Set<String> searchGroups( String filter ) throws Exception
182     {
183         return searchGroups( filter, null );
184     }
185 
186 
187     @Test
188     public void testLessThanSearchWithIndices() throws Exception
189     {
190         createData();
191         Set<String> results = searchGroups( "(gidNumber<=5)" );
192         assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
193         assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
194         assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
195         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
196         assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
197         assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
198 
199         results = searchGroups( "(gidNumber<=4)" );
200         assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
201         assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
202         assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
203         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
204         assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
205         assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
206 
207         results = searchGroups( "(gidNumber<=3)" );
208         assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
209         assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
210         assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
211         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
212         assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
213         assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
214 
215         results = searchGroups( "(gidNumber<=0)" );
216         assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
217         assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
218         assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
219         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
220         assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
221         assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
222 
223         results = searchGroups( "(gidNumber<=-1)" );
224         assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
225         assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
226         assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
227         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
228         assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
229         assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
230     }
231 
232     
233     @Test
234     public void testGreaterThanSearchWithIndices() throws Exception
235     {
236         createData();
237         Set<String> results = searchGroups( "(gidNumber>=0)" );
238         assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
239         assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
240         assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
241         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
242         assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
243         assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
244 
245         results = searchGroups( "(gidNumber>=1)" );
246         assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
247         assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
248         assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
249         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
250         assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
251         assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
252 
253         results = searchGroups( "(gidNumber>=3)" );
254         assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
255         assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
256         assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
257         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
258         assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
259         assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
260 
261         results = searchGroups( "(gidNumber>=6)" );
262         assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
263         assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
264         assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
265         assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
266         assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
267         assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
268     }
269 }