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.xdbm.search.impl;
21  
22  
23  import static org.junit.Assert.*;
24  
25  import java.io.File;
26  import java.util.HashSet;
27  import java.util.Set;
28  import java.util.List;
29  import java.util.ArrayList;
30  
31  import org.apache.commons.io.FileUtils;
32  import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
33  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
34  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmStore;
35  import org.apache.directory.server.core.entry.ServerEntry;
36  import org.apache.directory.server.schema.SerializableComparator;
37  import org.apache.directory.server.schema.bootstrap.ApacheSchema;
38  import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
39  import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
40  import org.apache.directory.server.schema.bootstrap.CollectiveSchema;
41  import org.apache.directory.server.schema.bootstrap.CoreSchema;
42  import org.apache.directory.server.schema.bootstrap.Schema;
43  import org.apache.directory.server.schema.bootstrap.SystemSchema;
44  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
45  import org.apache.directory.server.schema.registries.DefaultOidRegistry;
46  import org.apache.directory.server.schema.registries.DefaultRegistries;
47  import org.apache.directory.server.schema.registries.OidRegistry;
48  import org.apache.directory.server.schema.registries.Registries;
49  import org.apache.directory.server.xdbm.ForwardIndexEntry;
50  import org.apache.directory.server.xdbm.Store;
51  import org.apache.directory.server.xdbm.IndexCursor;
52  import org.apache.directory.server.xdbm.search.Evaluator;
53  import org.apache.directory.server.xdbm.tools.StoreUtils;
54  import org.apache.directory.shared.ldap.constants.SchemaConstants;
55  import org.apache.directory.shared.ldap.filter.AndNode;
56  import org.apache.directory.shared.ldap.filter.ExprNode;
57  import org.apache.directory.shared.ldap.filter.FilterParser;
58  import org.apache.directory.shared.ldap.filter.PresenceNode;
59  import org.apache.directory.shared.ldap.filter.SubstringNode;
60  import org.junit.*;
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  
65  /**
66   * 
67   * Test class for AndCursor.
68   *
69   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
70   * @version $Rev$, $Date$
71   */
72  public class AndCursorTest
73  {
74      private static final Logger LOG = LoggerFactory.getLogger( AndCursorTest.class.getSimpleName() );
75  
76      File wkdir;
77      Store<ServerEntry> store;
78      Registries registries = null;
79      AttributeTypeRegistry attributeRegistry;
80      EvaluatorBuilder evaluatorBuilder;
81      CursorBuilder cursorBuilder;
82  
83      public AndCursorTest() throws Exception
84      {
85          // setup the standard registries
86          BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
87          OidRegistry oidRegistry = new DefaultOidRegistry();
88          registries = new DefaultRegistries( "bootstrap", loader, oidRegistry );
89          SerializableComparator.setRegistry( registries.getComparatorRegistry() );
90  
91          // load essential bootstrap schemas
92          Set<Schema> bootstrapSchemas = new HashSet<Schema>();
93          bootstrapSchemas.add( new ApachemetaSchema() );
94          bootstrapSchemas.add( new ApacheSchema() );
95          bootstrapSchemas.add( new CoreSchema() );
96          bootstrapSchemas.add( new SystemSchema() );
97          bootstrapSchemas.add( new CollectiveSchema() );
98          loader.loadWithDependencies( bootstrapSchemas, registries );
99          attributeRegistry = registries.getAttributeTypeRegistry();
100     }
101 
102 
103     @Before
104     public void createStore() throws Exception
105     {
106         destryStore();
107 
108         // setup the working directory for the store
109         wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
110         wkdir.delete();
111         wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
112         wkdir.mkdirs();
113 
114         // initialize the store
115         store = new JdbmStore<ServerEntry>();
116         store.setName( "example" );
117         store.setCacheSize( 10 );
118         store.setWorkingDirectory( wkdir );
119         store.setSyncOnWrite( false );
120 
121         store.addIndex( new JdbmIndex( SchemaConstants.OU_AT_OID ) );
122         store.addIndex( new JdbmIndex( SchemaConstants.CN_AT_OID ) );
123         StoreUtils.loadExampleData( store, registries );
124         
125         evaluatorBuilder = new EvaluatorBuilder( store, registries );
126         cursorBuilder = new CursorBuilder( store, evaluatorBuilder );
127         
128         LOG.debug( "Created new store" );
129     }
130 
131     
132     @After
133     public void destryStore() throws Exception
134     {
135         if ( store != null )
136         {
137             store.destroy();
138         }
139 
140         store = null;
141         if ( wkdir != null )
142         {
143             FileUtils.deleteDirectory( wkdir );
144         }
145 
146         wkdir = null;
147     }
148 
149     
150     @Test
151     public void testAndCursorWithCursorBuilder() throws Exception
152     {
153         String filter = "(&(cn=J*)(sn=*))";
154 
155         ExprNode exprNode = FilterParser.parse( filter );
156         
157         IndexCursor<?,ServerEntry> cursor = cursorBuilder.build( exprNode );
158         
159         cursor.beforeFirst();
160 
161         assertTrue( cursor.next() );
162         assertTrue( cursor.available() );
163         assertEquals( 8, ( long ) cursor.get().getId() );
164         assertEquals( "jack daniels", cursor.get().getValue() );
165         
166         assertTrue( cursor.next() );
167         assertTrue( cursor.available() );
168         assertEquals( 6, ( long ) cursor.get().getId() );
169         assertEquals( "jim bean", cursor.get().getValue() );
170         
171         assertTrue( cursor.next() );
172         assertTrue( cursor.available() );
173         assertEquals( 5, ( long ) cursor.get().getId() );
174         assertEquals( "johnny walker", cursor.get().getValue() );
175         
176         assertFalse( cursor.next() );
177         assertFalse( cursor.available() );
178         
179         cursor.close();
180         assertTrue( cursor.isClosed() );
181     }
182     
183     
184     @Test
185     public void testAndCursorWithManualFilter() throws Exception
186     {
187         AndNode andNode = new AndNode();
188         
189         List<Evaluator<? extends ExprNode,ServerEntry>> evaluators = new ArrayList<Evaluator<? extends ExprNode,ServerEntry>>();
190         Evaluator<? extends ExprNode, ServerEntry> eval;
191         
192         ExprNode exprNode = new SubstringNode( "cn", "J*", null );
193         eval = new SubstringEvaluator( ( SubstringNode ) exprNode, store, registries );
194         IndexCursor<?,ServerEntry> wrapped = new SubstringCursor( store, ( SubstringEvaluator ) eval );
195         
196         /* adding this results in NPE  adding Presence evaluator not 
197          Substring evaluator but adding Substring cursor as wrapped cursor */
198         // evaluators.add( eval ); 
199         
200         andNode.addNode( exprNode );
201         
202         exprNode = new PresenceNode( "sn" );
203         eval = new PresenceEvaluator( ( PresenceNode ) exprNode, store, registries );
204         evaluators.add( eval );
205         
206         andNode.addNode( exprNode );
207         
208         IndexCursor<?,ServerEntry> cursor = new AndCursor( wrapped, evaluators ); //cursorBuilder.build( andNode );
209         
210         cursor.beforeFirst();
211 
212         assertTrue( cursor.next() );
213         assertTrue( cursor.available() );
214         assertEquals( 8, ( long ) cursor.get().getId() );
215         assertEquals( "jack daniels", cursor.get().getValue() );
216         
217         cursor.first();
218         
219         assertTrue( cursor.next() );
220         assertTrue( cursor.available() );
221         assertEquals( 6, ( long ) cursor.get().getId() );
222         assertEquals( "jim bean", cursor.get().getValue() );
223         
224         assertTrue( cursor.next() );
225         assertTrue( cursor.available() );
226         assertEquals( 5, ( long ) cursor.get().getId() );
227         assertEquals( "johnny walker", cursor.get().getValue() );        
228         
229         assertFalse( cursor.next() );
230         assertFalse( cursor.available() );
231 
232         cursor.afterLast();
233         
234         assertTrue( cursor.previous() );
235         assertTrue( cursor.available() );
236         assertEquals( 5, ( long ) cursor.get().getId() );
237         assertEquals( "johnny walker", cursor.get().getValue() );
238         
239         cursor.last();
240         
241         assertTrue( cursor.previous() );
242         assertTrue( cursor.available() );
243         assertEquals( 6, ( long ) cursor.get().getId() );
244         assertEquals( "jim bean", cursor.get().getValue() );
245         
246         assertTrue( cursor.previous() );
247         assertTrue( cursor.available() );
248         assertEquals( 8, ( long ) cursor.get().getId() );
249         assertEquals( "jack daniels", cursor.get().getValue() );
250         
251         assertFalse( cursor.previous() );
252         assertFalse( cursor.available() );
253         
254         assertTrue( cursor.isElementReused() );
255 
256         try
257         {
258             cursor.get();
259             fail( "should fail with InvalidCursorPositionException" );
260         }
261         catch( InvalidCursorPositionException ice ) { }
262         
263         try
264         {
265             cursor.after( new ForwardIndexEntry() );
266             fail( "should fail with UnsupportedOperationException " );
267         }
268         catch( UnsupportedOperationException uoe ) {}
269         
270         try
271         {
272             cursor.before( new ForwardIndexEntry() );
273             fail( "should fail with UnsupportedOperationException " );
274         }
275         catch( UnsupportedOperationException uoe ) {}
276 
277     }
278     
279     
280 }