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 }