001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.core.interceptor.context; 021 022 023 import static org.apache.directory.shared.ldap.filter.SearchScope.ONELEVEL; 024 025 import java.util.Collection; 026 import java.util.HashSet; 027 import java.util.Set; 028 029 import javax.naming.NamingException; 030 import javax.naming.directory.SearchControls; 031 032 import org.apache.directory.server.core.CoreSession; 033 import org.apache.directory.shared.ldap.constants.SchemaConstants; 034 import org.apache.directory.shared.ldap.exception.LdapNoSuchAttributeException; 035 import org.apache.directory.shared.ldap.filter.SearchScope; 036 import org.apache.directory.shared.ldap.message.AliasDerefMode; 037 import org.apache.directory.shared.ldap.name.DN; 038 import org.apache.directory.shared.ldap.schema.AttributeType; 039 import org.apache.directory.shared.ldap.schema.AttributeTypeOptions; 040 import org.apache.directory.shared.ldap.schema.SchemaUtils; 041 import org.apache.directory.shared.ldap.util.ArrayUtils; 042 import org.apache.directory.shared.ldap.util.StringTools; 043 import org.slf4j.Logger; 044 import org.slf4j.LoggerFactory; 045 046 047 /** 048 * A context used for search related operations and used by all 049 * the Interceptors. 050 * 051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 052 * @version $Rev$, $Date$ 053 */ 054 public abstract class SearchingOperationContext extends AbstractOperationContext 055 { 056 /** The LoggerFactory used by this Interceptor */ 057 private static Logger LOG = LoggerFactory.getLogger( SearchingOperationContext.class ); 058 059 /** A flag describing the way alias should be handled */ 060 protected AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS; 061 062 /** The sizeLimit for this search operation */ 063 protected long sizeLimit = 0; 064 065 /** The timeLimit for this search operation */ 066 protected int timeLimit = 0; 067 068 /** The scope for this search : default to One Level */ 069 protected SearchScope scope = ONELEVEL; 070 071 /** A flag set if the returned attributes set contains '+' */ 072 protected boolean allOperationalAttributes = false; 073 074 /** A flag set if the returned attributes set contains '*' */ 075 protected boolean allUserAttributes = false; 076 077 /** A flag set if the returned attributes set contains '1.1' */ 078 protected boolean noAttributes = false; 079 080 /** A set containing the returning attributeTypesOptions */ 081 protected Set<AttributeTypeOptions> returningAttributes; 082 083 /** A flag if the search operation is abandoned */ 084 protected boolean abandoned = false; 085 086 /** A flag to tell if only the attribute names to be returned */ 087 protected boolean typesOnly = false; 088 089 /** 090 * Creates a new instance of SearchingOperationContext. 091 */ 092 public SearchingOperationContext( CoreSession session ) 093 { 094 super( session ); 095 } 096 097 098 /** 099 * Creates a new instance of SearchingOperationContext. 100 * 101 * @param dn The DN to get the suffix from 102 */ 103 public SearchingOperationContext( CoreSession session, DN dn ) 104 { 105 super( session, dn ); 106 } 107 108 109 /** 110 * Creates a new instance of a SearchingOperationContext using one level 111 * scope, with attributes to return. 112 * 113 * @param dn The DN to get the suffix from 114 * @param aliasDerefMode the alias dereferencing mode to use 115 * @throws NamingException 116 */ 117 public SearchingOperationContext( CoreSession session, DN dn, Set<AttributeTypeOptions> returningAttributes ) 118 { 119 super( session, dn ); 120 this.returningAttributes = returningAttributes; 121 } 122 123 124 protected void setReturningAttributes( Collection<String> attributesIds ) 125 throws Exception 126 { 127 setReturningAttributes( attributesIds.toArray( StringTools.EMPTY_STRINGS ) ); 128 } 129 130 131 protected void setReturningAttributes( String[] attributesIds ) throws Exception 132 { 133 if ( attributesIds != null && attributesIds.length != 0 ) 134 { 135 returningAttributes = new HashSet<AttributeTypeOptions>(); 136 137 for ( String returnAttribute : attributesIds ) 138 { 139 if ( returnAttribute.equals( SchemaConstants.NO_ATTRIBUTE ) ) 140 { 141 noAttributes = true; 142 continue; 143 } 144 145 if ( returnAttribute.equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) ) 146 { 147 allOperationalAttributes = true; 148 continue; 149 } 150 151 if ( returnAttribute.equals( SchemaConstants.ALL_USER_ATTRIBUTES ) ) 152 { 153 allUserAttributes = true; 154 continue; 155 } 156 157 try 158 { 159 String id = SchemaUtils.stripOptions( returnAttribute ); 160 Set<String> options = SchemaUtils.getOptions( returnAttribute ); 161 162 AttributeType attributeType = session.getDirectoryService() 163 .getSchemaManager().lookupAttributeTypeRegistry( id ); 164 AttributeTypeOptions attrOptions = new AttributeTypeOptions( attributeType, options ); 165 166 returningAttributes.add( attrOptions ); 167 } 168 catch ( LdapNoSuchAttributeException nsae ) 169 { 170 LOG.warn( "Requested attribute {} does not exist in the schema, it will be ignored", returnAttribute ); 171 // Unknown attributes should be silently ignored, as RFC 2251 states 172 } 173 } 174 175 // reset the noAttrubte flag if it is already set cause that will be ignored if any other AT is requested 176 if( noAttributes && ( allUserAttributes || allOperationalAttributes || ( ! returningAttributes.isEmpty() ) ) ) 177 { 178 noAttributes = false; 179 } 180 } 181 } 182 183 184 /** 185 * @see Object#toString() 186 */ 187 public String toString() 188 { 189 return "ListOperationContext with DN '" + getDn().getName() + "'"; 190 } 191 192 193 public AliasDerefMode getAliasDerefMode() 194 { 195 return aliasDerefMode; 196 } 197 198 199 public void setAliasDerefMode( AliasDerefMode aliasDerefMode ) 200 { 201 this.aliasDerefMode = aliasDerefMode; 202 } 203 204 205 /** 206 * @param sizeLimit the sizeLimit to set 207 */ 208 public void setSizeLimit( long sizeLimit ) 209 { 210 this.sizeLimit = sizeLimit; 211 } 212 213 214 /** 215 * @return the sizeLimit 216 */ 217 public long getSizeLimit() 218 { 219 return sizeLimit; 220 } 221 222 223 /** 224 * @param timeLimit the timeLimit to set 225 */ 226 public void setTimeLimit( int timeLimit ) 227 { 228 this.timeLimit = timeLimit; 229 } 230 231 232 /** 233 * @return the timeLimit 234 */ 235 public int getTimeLimit() 236 { 237 return timeLimit; 238 } 239 240 241 /** 242 * @param scope the scope to set 243 */ 244 public void setScope( SearchScope scope ) 245 { 246 this.scope = scope; 247 } 248 249 250 /** 251 * @return the scope 252 */ 253 public SearchScope getScope() 254 { 255 return scope; 256 } 257 258 259 /** 260 * @param allOperationalAttributes the allOperationalAttributes to set 261 */ 262 public void setAllOperationalAttributes( boolean allOperationalAttribute ) 263 { 264 this.allOperationalAttributes = allOperationalAttribute; 265 } 266 267 268 /** 269 * @return the allOperationalAttributes 270 */ 271 public boolean isAllOperationalAttributes() 272 { 273 return allOperationalAttributes; 274 } 275 276 277 /** 278 * @param allUserAttributes the allUserAttributes to set 279 */ 280 public void setAllUserAttributes( boolean allUserAttributes ) 281 { 282 this.allUserAttributes = allUserAttributes; 283 } 284 285 286 /** 287 * @return the allUserAttributes 288 */ 289 public boolean isAllUserAttributes() 290 { 291 return allUserAttributes; 292 } 293 294 295 /** 296 * @param noAttributes the noAttributes to set 297 */ 298 public void setNoAttributes( boolean noAttributes ) 299 { 300 this.noAttributes = noAttributes; 301 } 302 303 304 /** 305 * @return the noAttributes 306 */ 307 public boolean isNoAttributes() 308 { 309 return noAttributes; 310 } 311 312 313 /** 314 * @return true, if attribute descriptions alone need to be returned 315 */ 316 public boolean isTypesOnly() 317 { 318 return typesOnly; 319 } 320 321 322 public void setTypesOnly( boolean typesOnly ) 323 { 324 this.typesOnly = typesOnly; 325 } 326 327 328 /** 329 * @param returningAttributes the returningAttributes to set 330 */ 331 public void setReturningAttributes( Set<AttributeTypeOptions> returningAttributes ) 332 { 333 this.returningAttributes = returningAttributes; 334 } 335 336 337 /** 338 * @return the returningAttributes 339 */ 340 public Set<AttributeTypeOptions> getReturningAttributes() 341 { 342 return returningAttributes; 343 } 344 345 346 /** 347 * Creates a new SearchControls object populated with the parameters 348 * contained in this SearchOperationContext in normalized form. 349 * 350 * @return a new SearchControls object 351 */ 352 public SearchControls getSearchControls() 353 { 354 return getSearchControls( false ); 355 } 356 357 358 /** 359 * Creates a new SearchControls object populated with the parameters 360 * contained in this SearchOperationContext. 361 * 362 * @param denormalized true if attribute values are <b>not</b> normalized 363 * @return a new SearchControls object 364 */ 365 public SearchControls getSearchControls( boolean denormalized ) 366 { 367 SearchControls controls = new SearchControls(); 368 controls.setCountLimit( sizeLimit ); 369 controls.setSearchScope( scope.getScope() ); 370 controls.setTimeLimit( timeLimit ); 371 372 Set<String> allReturningAttributes = new HashSet<String>(); 373 374 if ( noAttributes ) 375 { 376 allReturningAttributes.add( SchemaConstants.NO_ATTRIBUTE ); 377 } 378 379 if ( allUserAttributes ) 380 { 381 allReturningAttributes.add( SchemaConstants.ALL_USER_ATTRIBUTES ); 382 } 383 384 if ( allOperationalAttributes ) 385 { 386 allReturningAttributes.add( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ); 387 } 388 389 if ( returningAttributes != null ) 390 { 391 for ( AttributeTypeOptions at : returningAttributes ) 392 { 393 if ( denormalized ) 394 { 395 allReturningAttributes.add( at.getAttributeType().getName() ); 396 } 397 else 398 { 399 allReturningAttributes.add( at.getAttributeType().getOid() ); 400 } 401 } 402 } 403 404 if ( allReturningAttributes.size() > 0 ) 405 { 406 controls.setReturningAttributes( allReturningAttributes.toArray( ArrayUtils.EMPTY_STRING_ARRAY ) ); 407 } 408 409 return controls; 410 } 411 412 413 /** 414 * @param abandoned the abandoned to set 415 */ 416 public void setAbandoned( boolean abandoned ) 417 { 418 this.abandoned = abandoned; 419 } 420 421 422 /** 423 * @return the abandoned 424 */ 425 public boolean isAbandoned() 426 { 427 return abandoned; 428 } 429 }