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 */
020package org.apache.directory.server.core.api.interceptor.context;
021
022
023import java.util.Collection;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.directory.api.ldap.model.entry.Entry;
029import org.apache.directory.api.ldap.model.exception.LdapException;
030import org.apache.directory.api.ldap.model.message.Control;
031import org.apache.directory.api.ldap.model.name.Dn;
032import org.apache.directory.server.core.api.CoreSession;
033import org.apache.directory.server.core.api.LdapPrincipal;
034import org.apache.directory.server.core.api.partition.Partition;
035import org.apache.directory.server.core.api.partition.PartitionTxn;
036
037
038/**
039 * This abstract class stores common context elements, like the Dn, which is used
040 * in all the contexts.
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public abstract class AbstractOperationContext implements OperationContext
045{
046    protected static final Control[] EMPTY_CONTROLS = new Control[0];
047
048    /** The Dn associated with the context */
049    protected Dn dn;
050
051    /** The entry associated with the target entry of this OperationContext */
052    protected Entry entry;
053
054    /** The original Entry */
055    protected Entry originalEntry;
056
057    /** The associated request's controls */
058    protected Map<String, Control> requestControls = new HashMap<>( 4 );
059
060    /** The associated response's controls */
061    protected Map<String, Control> responseControls = new HashMap<>( 4 );
062
063    /** the Interceptors bypassed by this operation */
064    protected Collection<String> byPassed;
065
066    /** The interceptors to call for this operation */
067    protected List<String> interceptors;
068
069    /** The current interceptor position */
070    protected int currentInterceptor;
071
072    protected LdapPrincipal authorizedPrincipal;
073
074    /** The core session */
075    protected CoreSession session;
076
077    /** A flag used to tell if we should consider referrals as standard entries */
078    protected boolean throwReferral;
079    
080    /** The transaction this operation is ran into */
081    protected PartitionTxn transaction;
082    
083    /** The partition this operation will be applied on */
084    protected Partition partition;
085
086
087    /**
088     * Creates a new instance of AbstractOperationContext.
089     * 
090     * @param session The session to use
091     */
092    public AbstractOperationContext( CoreSession session )
093    {
094        this.session = session;
095        currentInterceptor = 0;
096    }
097
098
099    /**
100     * Creates a new instance of AbstractOperationContext.
101     *
102     * @param session The session to use
103     * @param dn The associated Dn
104     */
105    public AbstractOperationContext( CoreSession session, Dn dn )
106    {
107        this.dn = dn;
108        this.session = session;
109
110        // The flag is set to ignore, so that the revert operation can act on
111        // the entries, even if they are referrals.
112        ignoreReferral();
113    }
114
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public CoreSession getSession()
121    {
122        return session;
123    }
124
125
126    /**
127     * {@inheritDoc}
128     */
129    public void setSession( CoreSession session )
130    {
131        this.session = session;
132    }
133
134
135    /**
136     * {@inheritDoc}
137     */
138    protected void setAuthorizedPrincipal( LdapPrincipal authorizedPrincipal )
139    {
140        this.authorizedPrincipal = authorizedPrincipal;
141    }
142
143
144    /**
145     * @return The associated Dn
146     */
147    @Override
148    public Dn getDn()
149    {
150        return dn;
151    }
152
153
154    /**
155     * Set the context Dn
156     *
157     * @param dn The Dn to set
158     */
159    @Override
160    public void setDn( Dn dn )
161    {
162        this.dn = dn;
163    }
164
165
166    /**
167     * {@inheritDoc}
168     */
169    @Override
170    public void addRequestControl( Control requestControl )
171    {
172        requestControls.put( requestControl.getOid(), requestControl );
173    }
174
175
176    /**
177     * {@inheritDoc}
178     */
179    @Override
180    public Control getRequestControl( String numericOid )
181    {
182        return requestControls.get( numericOid );
183    }
184
185
186    /**
187     * {@inheritDoc}
188     */
189    @Override
190    public boolean hasRequestControl( String numericOid )
191    {
192        return requestControls.containsKey( numericOid );
193    }
194
195
196    /**
197     * {@inheritDoc}
198     */
199    @Override
200    public boolean hasRequestControls()
201    {
202        return !requestControls.isEmpty();
203    }
204
205
206    /**
207     * {@inheritDoc}
208     */
209    @Override
210    public void addResponseControl( Control responseControl )
211    {
212        responseControls.put( responseControl.getOid(), responseControl );
213    }
214
215
216    /**
217     * {@inheritDoc}
218     */
219    @Override
220    public Control getResponseControl( String numericOid )
221    {
222        return responseControls.get( numericOid );
223    }
224
225
226    /**
227     * {@inheritDoc}
228     */
229    @Override
230    public boolean hasResponseControl( String numericOid )
231    {
232        return responseControls.containsKey( numericOid );
233    }
234
235
236    /**
237     * {@inheritDoc}
238     */
239    @Override
240    public Control[] getResponseControls()
241    {
242        if ( responseControls.isEmpty() )
243        {
244            return EMPTY_CONTROLS;
245        }
246
247        return responseControls.values().toArray( EMPTY_CONTROLS );
248    }
249
250
251    /**
252     * {@inheritDoc}
253     */
254    @Override
255    public boolean hasResponseControls()
256    {
257        return !responseControls.isEmpty();
258    }
259
260
261    /**
262     * {@inheritDoc}
263     */
264    @Override
265    public int getResponseControlCount()
266    {
267        return responseControls.size();
268    }
269
270
271    /**
272     * {@inheritDoc}
273     */
274    @Override
275    public void addRequestControls( Control[] requestControls )
276    {
277        for ( Control c : requestControls )
278        {
279            this.requestControls.put( c.getOid(), c );
280        }
281    }
282
283
284    /**
285     * {@inheritDoc}
286     */
287    public void setRequestControls( Map<String, Control> requestControls )
288    {
289        this.requestControls = requestControls;
290    }
291
292
293    /**
294     * @return the originalEntry
295     */
296    public Entry getOriginalEntry()
297    {
298        return originalEntry;
299    }
300
301
302    /**
303     * @param originalEntry the originalEntry to set
304     */
305    public void setOriginalEntry( Entry originalEntry )
306    {
307        this.originalEntry = originalEntry;
308    }
309
310
311    /**
312     * {@inheritDoc}
313     */
314    @Override
315    public final void setInterceptors( List<String> interceptors )
316    {
317        this.interceptors = interceptors;
318    }
319
320
321    /**
322     * {@inheritDoc}
323     */
324    @Override
325    public final String getNextInterceptor()
326    {
327        if ( currentInterceptor == interceptors.size() )
328        {
329            return "FINAL";
330        }
331
332        String interceptor = interceptors.get( currentInterceptor );
333        currentInterceptor++;
334
335        return interceptor;
336    }
337
338
339    /**
340     * @return The number of the current interceptor in the list
341     */
342    @Override
343    public int getCurrentInterceptor()
344    {
345        return currentInterceptor;
346    }
347
348
349    /**
350     * Sets the current interceptor number to a new value.
351     * 
352     * @param currentInterceptor The new current interceptor value
353     */
354    @Override
355    public void setCurrentInterceptor( int currentInterceptor )
356    {
357        this.currentInterceptor = currentInterceptor;
358    }
359
360
361    private void setup( AbstractOperationContext opContext )
362    {
363        opContext.setAuthorizedPrincipal( authorizedPrincipal );
364    }
365
366
367    /**
368     * {@inheritDoc}
369     */
370    @Override
371    public void delete( Dn dn ) throws LdapException
372    {
373        DeleteOperationContext deleteContext = new DeleteOperationContext( session, dn );
374        setup( deleteContext );
375        session.getDirectoryService().getOperationManager().delete( deleteContext );
376    }
377
378
379    /**
380     * {@inheritDoc}
381     */
382    @Override
383    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
384    {
385        return session.getDirectoryService().getOperationManager().lookup( lookupContext );
386    }
387
388
389    // TODO - need synchronization here and where we update links
390    /**
391     * {@inheritDoc}
392     */
393    @Override
394    public LookupOperationContext newLookupContext( Dn dn, String... attributes )
395    {
396        LookupOperationContext lookupContext = new LookupOperationContext( session, dn, attributes );
397        setup( lookupContext );
398
399        return lookupContext;
400    }
401
402
403    /**
404     * {@inheritDoc}
405     */
406    @Override
407    public LdapPrincipal getEffectivePrincipal()
408    {
409        if ( authorizedPrincipal != null )
410        {
411            return authorizedPrincipal;
412        }
413
414        return session.getEffectivePrincipal();
415    }
416
417
418    // -----------------------------------------------------------------------
419    // OperationContext Linked List Methods
420    // -----------------------------------------------------------------------
421    /**
422     * @param entry the entry to set
423     */
424    @Override
425    public void setEntry( Entry entry )
426    {
427        this.entry = entry;
428    }
429
430
431    /**
432     * @return the entry
433     */
434    @Override
435    public Entry getEntry()
436    {
437        return entry;
438    }
439
440
441    /**
442     * Set the throwReferral flag to true
443     */
444    @Override
445    public void throwReferral()
446    {
447        throwReferral = true;
448    }
449
450
451    /**
452     * @return <code>true</code> if the referrals are thrown
453     */
454    @Override
455    public boolean isReferralThrown()
456    {
457        return throwReferral;
458    }
459
460
461    /**
462     * Set the throwReferral flag to false
463     */
464    @Override
465    public void ignoreReferral()
466    {
467        throwReferral = false;
468    }
469
470
471    /**
472     * @return <code>true</code> if the referrals are ignored
473     */
474    @Override
475    public boolean isReferralIgnored()
476    {
477        return !throwReferral;
478    }
479
480
481    /**
482     * @return the transaction
483     */
484    @Override
485    public PartitionTxn getTransaction()
486    {
487        return transaction;
488    }
489
490
491    /**
492     * @param transaction the transaction to set
493     */
494    @Override
495    public void setTransaction( PartitionTxn transaction )
496    {
497        this.transaction = transaction;
498    }
499    
500    
501    /**
502     * {@inheritDoc}
503     */
504    @Override
505    public Partition getPartition()
506    {
507        return partition;
508    }
509    
510    
511    /**
512     * {@inheritDoc}
513     */
514    @Override
515    public void setPartition( Partition partition )
516    {
517        this.partition = partition;
518    }
519}