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 org.apache.directory.shared.ldap.filter.ScopeNode; 24 import org.apache.directory.shared.ldap.filter.SearchScope; 25 import org.apache.directory.server.xdbm.IndexEntry; 26 import org.apache.directory.server.xdbm.Store; 27 import org.apache.directory.server.xdbm.search.Evaluator; 28 29 30 /** 31 * Evaluates one level scope assertions on candidates using an entry database. 32 * 33 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 34 * @version $Rev: 659774 $ 35 */ 36 public class OneLevelScopeEvaluator<E> implements Evaluator<ScopeNode,E> 37 { 38 /** The ScopeNode containing initial search scope constraints */ 39 private final ScopeNode node; 40 41 /** The entry identifier of the scope base */ 42 private final Long baseId; 43 44 /** True if the scope requires alias dereferencing while searching */ 45 private final boolean dereferencing; 46 47 /** the entry db storing entries */ 48 private final Store<E> db; 49 50 51 /** 52 * Creates a one level scope node Evaluator for search expressions. 53 * 54 * @param node the scope node 55 * @param db the database used to evaluate scope node 56 * @throws Exception on db access failure 57 */ 58 public OneLevelScopeEvaluator( Store<E> db, ScopeNode node ) throws Exception 59 { 60 this.node = node; 61 62 if ( node.getScope() != SearchScope.ONELEVEL ) 63 { 64 throw new IllegalStateException( "ScopeNode is not of onelevel scope." ); 65 } 66 67 this.db = db; 68 baseId = db.getEntryId( node.getBaseDn() ); 69 dereferencing = node.getDerefAliases().isDerefInSearching() || 70 node.getDerefAliases().isDerefAlways(); 71 } 72 73 74 /** 75 * Asserts whether or not a candidate has one level scope while taking 76 * alias dereferencing into account. 77 * 78 * @param candidate the candidate to assert 79 * @return true if the candidate is within one level scope 80 * @throws Exception if db lookups fail 81 * @see org.apache.directory.server.xdbm.search.Evaluator#evaluate(IndexEntry) 82 */ 83 public boolean evaluate( Long candidate ) throws Exception 84 { 85 boolean isChild = db.getOneLevelIndex().forward( baseId, candidate ); 86 87 /* 88 * The candidate id could be any entry in the db. If search 89 * dereferencing is not enabled then we return the results of the child 90 * test. 91 */ 92 if ( ! dereferencing ) 93 { 94 return isChild; 95 } 96 97 /* 98 * From here down alias dereferencing is enabled. We determine if the 99 * candidate id is an alias, if so we reject it since aliases should 100 * not be returned. 101 */ 102 if ( null != db.getAliasIndex().reverseLookup( candidate ) ) 103 { 104 return false; 105 } 106 107 /* 108 * The candidate is NOT an alias at this point. So if it is a child we 109 * just return true since it is in normal one level scope. 110 */ 111 if ( isChild ) 112 { 113 return true; 114 } 115 116 /* 117 * At this point the candidate is not a child and it is not an alias. 118 * We need to check if the candidate is in extended one level scope by 119 * performing a lookup on the one level alias index. This index stores 120 * a tuple mapping the baseId to the id of objects brought into the 121 * one level scope of the base by an alias: ( baseId, aliasedObjId ) 122 * If the candidate id is an object brought into one level scope then 123 * the lookup returns true accepting the candidate. Otherwise the 124 * candidate is rejected with a false return because it is not in scope. 125 */ 126 return db.getOneAliasIndex().forward( baseId, candidate ); 127 } 128 129 130 /** 131 * Asserts whether or not a candidate has one level scope while taking 132 * alias dereferencing into account. 133 * 134 * TODO - terribly inefficient - would benefit from exposing the id of an 135 * entry within the ServerEntry 136 * 137 * @see Evaluator#evaluate(Object) 138 */ 139 public boolean evaluate( E candidate ) throws Exception 140 { 141 throw new UnsupportedOperationException( "This is too inefficient without getId() on ServerEntry" ); 142 } 143 144 145 /** 146 * Asserts whether or not a candidate has one level scope while taking 147 * alias dereferencing into account. 148 * 149 * @param candidate the candidate to assert 150 * @return true if the candidate is within one level scope 151 * @throws Exception if db lookups fail 152 * @see org.apache.directory.server.xdbm.search.Evaluator#evaluate(IndexEntry) 153 */ 154 public boolean evaluate( IndexEntry<?,E> candidate ) throws Exception 155 { 156 boolean isChild = db.getOneLevelIndex().forward( baseId, candidate.getId() ); 157 158 /* 159 * The candidate id could be any entry in the db. If search 160 * dereferencing is not enabled then we return the results of the child 161 * test. 162 */ 163 if ( ! dereferencing ) 164 { 165 return isChild; 166 } 167 168 /* 169 * From here down alias dereferencing is enabled. We determine if the 170 * candidate id is an alias, if so we reject it since aliases should 171 * not be returned. 172 */ 173 if ( null != db.getAliasIndex().reverseLookup( candidate.getId() ) ) 174 { 175 return false; 176 } 177 178 /* 179 * The candidate is NOT an alias at this point. So if it is a child we 180 * just return true since it is in normal one level scope. 181 */ 182 if ( isChild ) 183 { 184 return true; 185 } 186 187 /* 188 * At this point the candidate is not a child and it is not an alias. 189 * We need to check if the candidate is in extended one level scope by 190 * performing a lookup on the one level alias index. This index stores 191 * a tuple mapping the baseId to the id of objects brought into the 192 * one level scope of the base by an alias: ( baseId, aliasedObjId ) 193 * If the candidate id is an object brought into one level scope then 194 * the lookup returns true accepting the candidate. Otherwise the 195 * candidate is rejected with a false return because it is not in scope. 196 */ 197 return db.getOneAliasIndex().forward( baseId, candidate.getId() ); 198 } 199 200 201 public ScopeNode getExpression() 202 { 203 return node; 204 } 205 206 207 /** 208 * Gets the id of the search base associated with the ScopeNode expression. 209 * 210 * @return identifier of the search base 211 */ 212 public Long getBaseId() 213 { 214 return baseId; 215 } 216 217 218 /** 219 * Gets whether or not dereferencing is enabled for this evaluator. 220 * 221 * @return true if dereferencing is enabled, false otherwise 222 */ 223 public boolean isDereferencing() 224 { 225 return dereferencing; 226 } 227 }