View Javadoc

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.interceptor.context;
21  
22  
23  import java.util.Collection;
24  import java.util.HashSet;
25  import java.util.Set;
26  
27  import javax.naming.NamingException;
28  import javax.naming.directory.NoSuchAttributeException;
29  import javax.naming.directory.SearchControls;
30  
31  import org.apache.directory.server.core.CoreSession;
32  import org.apache.directory.shared.ldap.constants.SchemaConstants;
33  import org.apache.directory.shared.ldap.filter.SearchScope;
34  import org.apache.directory.shared.ldap.message.AliasDerefMode;
35  import org.apache.directory.shared.ldap.name.LdapDN;
36  import org.apache.directory.shared.ldap.schema.AttributeType;
37  import org.apache.directory.shared.ldap.schema.AttributeTypeOptions;
38  import org.apache.directory.shared.ldap.schema.SchemaUtils;
39  import org.apache.directory.shared.ldap.util.ArrayUtils;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  import static org.apache.directory.shared.ldap.filter.SearchScope.ONELEVEL;
44  
45  
46  /**
47   * A context used for search related operations and used by all 
48   * the Interceptors.
49   *
50   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
51   * @version $Rev$, $Date$
52   */
53  public abstract class SearchingOperationContext extends AbstractOperationContext
54  {
55      /** The LoggerFactory used by this Interceptor */
56      private static Logger LOG = LoggerFactory.getLogger( SearchingOperationContext.class );
57      
58      private static String[] EMPTY_STR_ARRAY = new String[0];
59  
60      /** A flag describing the way alias should be handled */
61      protected AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
62  
63      /** The sizeLimit for this search operation */
64      protected long sizeLimit = 0;
65      
66      /** The timeLimit for this search operation */
67      protected int timeLimit = 0;
68      
69      /** The scope for this search : default to One Level */
70      protected SearchScope scope = ONELEVEL;
71  
72      /** A flag set if the returned attributes set contains '+' */
73      protected boolean allOperationalAttributes = false;
74      
75      /** A flag set if the returned attributes set contains '*' */
76      protected boolean allUserAttributes = false;
77      
78      /** A flag set if the returned attributes set contains '1.1' */
79      protected boolean noAttributes = false;
80      
81      /** A set containing the returning attributeTypesOptions */
82      protected Set<AttributeTypeOptions> returningAttributes; 
83      
84      /** A flag if the search operation is abandoned */
85      protected boolean abandoned = false;
86      
87      
88      /**
89       * Creates a new instance of ListOperationContext.
90       */
91      public SearchingOperationContext( CoreSession session )
92      {
93          super( session );
94      }
95  
96  
97      /**
98       * Creates a new instance of ListOperationContext.
99       *
100      * @param dn The DN to get the suffix from
101      */
102     public SearchingOperationContext( CoreSession session, LdapDN dn )
103     {
104         super( session, dn );
105     }
106 
107 
108     /**
109      * Creates a new instance of ListOperationContext.
110      *
111      * @param dn The DN to get the suffix from
112      * @param aliasDerefMode the alias dereferencing mode to use
113      */
114     public SearchingOperationContext( CoreSession session, LdapDN dn, AliasDerefMode aliasDerefMode )
115     {
116         super( session, dn );
117         this.aliasDerefMode = aliasDerefMode;
118     }
119 
120     
121     protected void setReturningAttributes( Collection<String> attributesIds ) 
122         throws Exception
123     {
124         setReturningAttributes( attributesIds.toArray( EMPTY_STR_ARRAY ) );
125     }
126     
127     
128     protected void setReturningAttributes( String[] attributesIds ) throws Exception
129     {
130         if ( attributesIds != null && attributesIds.length != 0 )
131         {
132             returningAttributes = new HashSet<AttributeTypeOptions>();
133             
134             for ( String returnAttribute : attributesIds )
135             {
136                 if ( returnAttribute.equals( SchemaConstants.NO_ATTRIBUTE ) )
137                 {
138                     noAttributes = true;
139                     continue;
140                 }
141                 
142                 if ( returnAttribute.equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) )
143                 {
144                     allOperationalAttributes = true;
145                     continue;
146                 }
147                 
148                 if ( returnAttribute.equals( SchemaConstants.ALL_USER_ATTRIBUTES ) )
149                 {
150                     allUserAttributes = true;
151                     continue;
152                 }
153                 
154                 try
155                 {
156                     String id = SchemaUtils.stripOptions( returnAttribute );
157                     Set<String> options = SchemaUtils.getOptions( returnAttribute );
158                     
159                     AttributeType attributeType = session.getDirectoryService()
160                         .getRegistries().getAttributeTypeRegistry().lookup( id );
161                     AttributeTypeOptions attrOptions = new AttributeTypeOptions( attributeType, options );
162                     
163                     returningAttributes.add( attrOptions );
164                 }
165                 catch ( NoSuchAttributeException nsae )
166                 {
167                     LOG.warn( "Requested attribute {} does not exist in the schema, it will be ignored", returnAttribute );
168                     // Unknown attributes should be silently ignored, as RFC 2251 states
169                 }
170             }
171         }
172     }
173     
174     
175     /**
176      * Creates a new instance of ListOperationContext.
177      *
178      * @param dn The DN to get the suffix from
179      * @param aliasDerefMode the alias dereferencing mode to use
180      * @throws NamingException 
181      */
182     public SearchingOperationContext( CoreSession session, LdapDN dn, AliasDerefMode aliasDerefMode, 
183         SearchControls searchControls ) throws Exception
184     {
185         super( session, dn );
186         this.aliasDerefMode = aliasDerefMode;
187         this.scope = SearchScope.getSearchScope( searchControls );
188         this.timeLimit = searchControls.getTimeLimit();
189         this.sizeLimit = searchControls.getCountLimit();
190         
191         if ( searchControls.getReturningAttributes() != null )
192         {
193             setReturningAttributes( searchControls.getReturningAttributes() );
194         }
195     }
196 
197     
198     /**
199      * Creates a new instance of a SearchingOperationContext using one level 
200      * scope, with attributes to return.
201      *
202      * @param dn The DN to get the suffix from
203      * @param aliasDerefMode the alias dereferencing mode to use
204      * @throws NamingException 
205      */
206     public SearchingOperationContext( CoreSession session, LdapDN dn, AliasDerefMode aliasDerefMode,
207         Set<AttributeTypeOptions> returningAttributes )
208     {
209         super( session, dn );
210         this.aliasDerefMode = aliasDerefMode;
211         this.returningAttributes = returningAttributes;
212     }
213 
214 
215     /**
216      * @see Object#toString()
217      */
218     public String toString()
219     {
220         return "ListOperationContext with DN '" + getDn().getUpName() + "'";
221     }
222 
223     
224     public AliasDerefMode getAliasDerefMode()
225     {
226         return aliasDerefMode;
227     }
228 
229 
230     /**
231      * @param sizeLimit the sizeLimit to set
232      */
233     public void setSizeLimit( long sizeLimit )
234     {
235         this.sizeLimit = sizeLimit;
236     }
237 
238 
239     /**
240      * @return the sizeLimit
241      */
242     public long getSizeLimit()
243     {
244         return sizeLimit;
245     }
246 
247 
248     /**
249      * @param timeLimit the timeLimit to set
250      */
251     public void setTimeLimit( int timeLimit )
252     {
253         this.timeLimit = timeLimit;
254     }
255 
256 
257     /**
258      * @return the timeLimit
259      */
260     public int getTimeLimit()
261     {
262         return timeLimit;
263     }
264 
265 
266     /**
267      * @param scope the scope to set
268      */
269     public void setScope( SearchScope scope )
270     {
271         this.scope = scope;
272     }
273 
274 
275     /**
276      * @return the scope
277      */
278     public SearchScope getScope()
279     {
280         return scope;
281     }
282 
283 
284     /**
285      * @param allOperationalAttributes the allOperationalAttributes to set
286      */
287     public void setAllOperationalAttributes( boolean allOperationalAttribute )
288     {
289         this.allOperationalAttributes = allOperationalAttribute;
290     }
291 
292 
293     /**
294      * @return the allOperationalAttributes
295      */
296     public boolean isAllOperationalAttributes()
297     {
298         return allOperationalAttributes;
299     }
300 
301 
302     /**
303      * @param allUserAttributes the allUserAttributes to set
304      */
305     public void setAllUserAttributes( boolean allUserAttributes )
306     {
307         this.allUserAttributes = allUserAttributes;
308     }
309 
310 
311     /**
312      * @return the allUserAttributes
313      */
314     public boolean isAllUserAttributes()
315     {
316         return allUserAttributes;
317     }
318 
319 
320     /**
321      * @param noAttributes the noAttributes to set
322      */
323     public void setNoAttributes( boolean noAttributes )
324     {
325         this.noAttributes = noAttributes;
326     }
327 
328 
329     /**
330      * @return the noAttributes
331      */
332     public boolean isNoAttributes()
333     {
334         return noAttributes;
335     }
336 
337 
338     /**
339      * @param returningAttributes the returningAttributes to set
340      */
341     public void setReturningAttributes( Set<AttributeTypeOptions> returningAttributes )
342     {
343         this.returningAttributes = returningAttributes;
344     }
345 
346 
347     /**
348      * @return the returningAttributes
349      */
350     public Set<AttributeTypeOptions> getReturningAttributes()
351     {
352         return returningAttributes;
353     }
354 
355     
356     /**
357      * Creates a new SearchControls object populated with the parameters 
358      * contained in this SearchOperationContext in normalized form.
359      *
360      * @return a new SearchControls object
361      */
362     public SearchControls getSearchControls()
363     {
364         return getSearchControls( false );
365     }
366     
367     
368     /**
369      * Creates a new SearchControls object populated with the parameters 
370      * contained in this SearchOperationContext.
371      *
372      * @param denormalized true if attribute values are <b>not</b> normalized
373      * @return a new SearchControls object
374      */
375     public SearchControls getSearchControls( boolean denormalized )
376     {
377         SearchControls controls = new SearchControls();
378         controls.setCountLimit( sizeLimit );
379         controls.setSearchScope( scope.getJndiScope() );
380         controls.setTimeLimit( timeLimit );
381 
382         Set<String> allReturningAttributes = new HashSet<String>();
383         
384         if ( noAttributes )
385         {
386             allReturningAttributes.add( SchemaConstants.NO_ATTRIBUTE );
387         }
388         
389         if ( allUserAttributes )
390         {
391             allReturningAttributes.add( SchemaConstants.ALL_USER_ATTRIBUTES );
392         }
393         
394         if ( allOperationalAttributes )
395         {
396             allReturningAttributes.add( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES );
397         }
398         
399         if ( returningAttributes != null )
400         {
401             for ( AttributeTypeOptions at : returningAttributes )
402             {
403                 if ( denormalized )
404                 {
405                     allReturningAttributes.add( at.getAttributeType().getName() );
406                 }
407                 else
408                 {
409                     allReturningAttributes.add( at.getAttributeType().getOid() );
410                 }
411             }
412         }
413         
414         if ( allReturningAttributes.size() > 0 )
415         {
416             controls.setReturningAttributes( allReturningAttributes.toArray( ArrayUtils.EMPTY_STRING_ARRAY ) );
417         }
418         
419         return controls;
420     }
421 
422 
423     /**
424      * @param abandoned the abandoned to set
425      */
426     public void setAbandoned( boolean abandoned )
427     {
428         this.abandoned = abandoned;
429     }
430 
431 
432     /**
433      * @return the abandoned
434      */
435     public boolean isAbandoned()
436     {
437         return abandoned;
438     }
439 }