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.shared;
21  
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.net.SocketAddress;
26  import java.nio.file.Files;
27  import java.text.ParseException;
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  import java.util.concurrent.atomic.AtomicLong;
35  
36  import jdbm.recman.BaseRecordManager;
37  
38  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncRequest.SyncRequestValue;
39  import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
40  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
41  import org.apache.directory.api.ldap.model.cursor.Cursor;
42  import org.apache.directory.api.ldap.model.cursor.CursorException;
43  import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
44  import org.apache.directory.api.ldap.model.entry.DefaultModification;
45  import org.apache.directory.api.ldap.model.entry.Entry;
46  import org.apache.directory.api.ldap.model.entry.Modification;
47  import org.apache.directory.api.ldap.model.entry.Value;
48  import org.apache.directory.api.ldap.model.exception.LdapException;
49  import org.apache.directory.api.ldap.model.exception.LdapInvalidSearchFilterException;
50  import org.apache.directory.api.ldap.model.filter.ExprNode;
51  import org.apache.directory.api.ldap.model.filter.FilterParser;
52  import org.apache.directory.api.ldap.model.filter.PresenceNode;
53  import org.apache.directory.api.ldap.model.message.AddRequest;
54  import org.apache.directory.api.ldap.model.message.AliasDerefMode;
55  import org.apache.directory.api.ldap.model.message.CompareRequest;
56  import org.apache.directory.api.ldap.model.message.Control;
57  import org.apache.directory.api.ldap.model.message.DeleteRequest;
58  import org.apache.directory.api.ldap.model.message.LdapResult;
59  import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
60  import org.apache.directory.api.ldap.model.message.ModifyRequest;
61  import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
62  import org.apache.directory.api.ldap.model.message.ResultResponse;
63  import org.apache.directory.api.ldap.model.message.SearchRequest;
64  import org.apache.directory.api.ldap.model.message.SearchScope;
65  import org.apache.directory.api.ldap.model.message.UnbindRequest;
66  import org.apache.directory.api.ldap.model.message.controls.SortKey;
67  import org.apache.directory.api.ldap.model.message.controls.SortRequest;
68  import org.apache.directory.api.ldap.model.message.controls.SortResponse;
69  import org.apache.directory.api.ldap.model.message.controls.SortResponseImpl;
70  import org.apache.directory.api.ldap.model.message.controls.SortResultCode;
71  import org.apache.directory.api.ldap.model.name.Dn;
72  import org.apache.directory.api.ldap.model.name.Rdn;
73  import org.apache.directory.api.ldap.model.schema.AttributeType;
74  import org.apache.directory.api.ldap.model.schema.MatchingRule;
75  import org.apache.directory.api.ldap.model.schema.SchemaManager;
76  import org.apache.directory.api.util.Strings;
77  import org.apache.directory.server.constants.ServerDNConstants;
78  import org.apache.directory.server.core.api.CoreSession;
79  import org.apache.directory.server.core.api.DirectoryService;
80  import org.apache.directory.server.core.api.LdapPrincipal;
81  import org.apache.directory.server.core.api.OperationManager;
82  import org.apache.directory.server.core.api.changelog.LogChange;
83  import org.apache.directory.server.core.api.interceptor.context.AbstractOperationContext;
84  import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
85  import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
86  import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
87  import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
88  import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
89  import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
90  import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
91  import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
92  import org.apache.directory.server.core.api.interceptor.context.OperationContext;
93  import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
94  import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
95  import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
96  import org.apache.directory.server.core.api.partition.Partition;
97  import org.apache.directory.server.core.api.partition.PartitionTxn;
98  import org.apache.directory.server.i18n.I18n;
99  import org.apache.mina.core.session.IoSession;
100 import org.slf4j.Logger;
101 import org.slf4j.LoggerFactory;
102 
103 
104 /**
105  * The default CoreSession implementation.
106  * 
107  * TODO - has not been completed yet
108  * TODO - need to supply controls and other parameters to setup opContexts
109  *
110  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
111  */
112 public class DefaultCoreSession implements CoreSession
113 {
114     /** A logger for this class */
115     private static final Logger LOG = LoggerFactory.getLogger( DefaultCoreSession.class );
116 
117     /** The DirectoryService we are connected to */
118     private final DirectoryService directoryService;
119 
120     /** The Principal used to process operations */
121     private final LdapPrincipal authenticatedPrincipal;
122 
123     /** The anonymous principal, if we have to process operation as anonymous */
124     private final LdapPrincipal anonymousPrincipal;
125 
126     /** The authorized principal, which will be used when a user has been authorized */
127     private LdapPrincipal authorizedPrincipal;
128 
129     /** A reference to the ObjectClass AT */
130     protected AttributeType objectClassAT;
131 
132     /** The associated IoSession */
133     private IoSession ioSession;
134 
135     /** flag to indicate if the password must be changed */
136     private boolean pwdMustChange;
137 
138     /** A flag set when the startTransaction extended operation has been received */
139     private boolean hasSessionTransaction;
140     
141     /** The Map containing the transactions associated with each partition */
142     private Map<String, PartitionTxn> transactionMap = new HashMap<>();
143     
144     /** The transaction ID */
145     private AtomicLong transactionId = new AtomicLong( 0 );
146 
147     /**
148      * Creates a new instance of a DefaultCoreSession
149      * @param principal The principal to use to process operation for this session
150      * @param directoryService The DirectoryService to which we will send requests
151      */
152     public DefaultCoreSession( LdapPrincipal principal, DirectoryService directoryService )
153     {
154         this.directoryService = directoryService;
155         authenticatedPrincipal = principal;
156 
157         if ( principal.getAuthenticationLevel() == AuthenticationLevel.NONE )
158         {
159             anonymousPrincipal = principal;
160         }
161         else
162         {
163             anonymousPrincipal = new LdapPrincipal( directoryService.getSchemaManager() );
164         }
165 
166         // setup attribute type value
167         objectClassAT = directoryService.getSchemaManager().getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
168     }
169 
170 
171     /**
172      * Gets the IoSession from the CoreSession. This is only useful when the server is not embedded.
173      * 
174      * @return ioSession The IoSession for this CoreSession
175      */
176     public IoSession getIoSession()
177     {
178         return ioSession;
179     }
180 
181 
182     /**
183      * Stores the IoSession into the CoreSession. This is only useful when the server is not embedded.
184      * 
185      * @param ioSession The IoSession for this CoreSession
186      */
187     public void setIoSession( IoSession ioSession )
188     {
189         this.ioSession = ioSession;
190     }
191 
192 
193     /**
194      * Set the ignoreRefferal flag for the current operationContext.
195      *
196      * @param opContext The current operationContext
197      * @param ignoreReferral The flag
198      */
199     private void setReferralHandling( AbstractOperationContext opContext, boolean ignoreReferral )
200     {
201         if ( ignoreReferral )
202         {
203             opContext.ignoreReferral();
204         }
205         else
206         {
207             opContext.throwReferral();
208         }
209     }
210 
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
216     public void add( Entry entry ) throws LdapException
217     {
218         add( entry, LogChange.TRUE );
219     }
220 
221 
222     /**
223      * {@inheritDoc}
224      */
225     @Override
226     public void add( Entry entry, boolean ignoreReferral ) throws LdapException
227     {
228         add( entry, ignoreReferral, LogChange.TRUE );
229     }
230 
231 
232     /**
233      * {@inheritDoc}
234      */
235     @Override
236     public void add( Entry entry, LogChange log ) throws LdapException
237     {
238         AddOperationContextterceptor/context/AddOperationContext.html#AddOperationContext">AddOperationContext addContext = new AddOperationContext( this, entry );
239 
240         addContext.setLogChange( log );
241 
242         OperationManager operationManager = directoryService.getOperationManager();
243         operationManager.add( addContext );
244     }
245 
246 
247     /**
248      * {@inheritDoc}
249      */
250     @Override
251     public void add( Entry entry, boolean ignoreReferral, LogChange log ) throws LdapException
252     {
253         AddOperationContextterceptor/context/AddOperationContext.html#AddOperationContext">AddOperationContext addContext = new AddOperationContext( this, entry );
254 
255         addContext.setLogChange( log );
256         setReferralHandling( addContext, ignoreReferral );
257 
258         OperationManager operationManager = directoryService.getOperationManager();
259         operationManager.add( addContext );
260     }
261 
262 
263     /**
264      * {@inheritDoc}
265      */
266     @Override
267     public void add( AddRequest addRequest ) throws LdapException
268     {
269         add( addRequest, LogChange.TRUE );
270     }
271 
272 
273     /**
274      * {@inheritDoc}
275      */
276     @Override
277     public void add( AddRequest addRequest, LogChange log ) throws LdapException
278     {
279         AddOperationContextterceptor/context/AddOperationContext.html#AddOperationContext">AddOperationContext addContext = new AddOperationContext( this, addRequest );
280 
281         addContext.setLogChange( log );
282 
283         OperationManager operationManager = directoryService.getOperationManager();
284         
285         try
286         {
287             operationManager.add( addContext );
288         }
289         catch ( LdapException e )
290         {
291             addRequest.getResultResponse().addAllControls( addContext.getResponseControls() );
292             throw e;
293         }
294         
295         addRequest.getResultResponse().addAllControls( addContext.getResponseControls() );
296     }
297 
298 
299     private Value convertToValue( String oid, Object value ) throws LdapException
300     {
301         Value val;
302 
303         AttributeType attributeType = directoryService.getSchemaManager().lookupAttributeTypeRegistry( oid );
304 
305         // make sure we add the request controls to operation
306         if ( attributeType.getSyntax().isHumanReadable() )
307         {
308             if ( value instanceof String )
309             {
310                 val = new Value( attributeType, ( String ) value );
311             }
312             else if ( value instanceof byte[] )
313             {
314                 val = new Value( attributeType, Strings.utf8ToString( ( byte[] ) value ) );
315             }
316             else
317             {
318                 throw new LdapException( I18n.err( I18n.ERR_309, oid ) );
319             }
320         }
321         else
322         {
323             if ( value instanceof String )
324             {
325                 val = new Value( attributeType, Strings.getBytesUtf8( ( String ) value ) );
326             }
327             else if ( value instanceof byte[] )
328             {
329                 val = new Value( attributeType, ( byte[] ) value );
330             }
331             else
332             {
333                 throw new LdapException( I18n.err( I18n.ERR_309, oid ) );
334             }
335         }
336 
337         return val;
338     }
339 
340 
341     /**
342      * {@inheritDoc}
343      */
344     @Override
345     public boolean compare( Dn dn, String oid, Object value ) throws LdapException
346     {
347         OperationManager operationManager = directoryService.getOperationManager();
348 
349         return operationManager.compare( new CompareOperationContext( this, dn, oid, convertToValue( oid, value ) ) );
350     }
351 
352 
353     /**
354      * {@inheritDoc}
355      */
356     @Override
357     public boolean compare( Dn dn, String oid, Object value, boolean ignoreReferral ) throws LdapException
358     {
359         CompareOperationContextr/context/CompareOperationContext.html#CompareOperationContext">CompareOperationContext compareContext = new CompareOperationContext( this, dn, oid,
360             convertToValue( oid, value ) );
361 
362         setReferralHandling( compareContext, ignoreReferral );
363 
364         OperationManager operationManager = directoryService.getOperationManager();
365         return operationManager.compare( compareContext );
366     }
367 
368 
369     /**
370      * {@inheritDoc}
371      */
372     @Override
373     public void delete( Dn dn ) throws LdapException
374     {
375         delete( dn, LogChange.TRUE );
376     }
377 
378 
379     /**
380      * {@inheritDoc}
381      */
382     @Override
383     public void delete( Dn dn, LogChange log ) throws LdapException
384     {
385         DeleteOperationContexttor/context/DeleteOperationContext.html#DeleteOperationContext">DeleteOperationContext deleteContext = new DeleteOperationContext( this, dn );
386 
387         deleteContext.setLogChange( log );
388 
389         OperationManager operationManager = directoryService.getOperationManager();
390         operationManager.delete( deleteContext );
391     }
392 
393 
394     /**
395      * {@inheritDoc}
396      */
397     @Override
398     public void delete( Dn dn, boolean ignoreReferral ) throws LdapException
399     {
400         delete( dn, ignoreReferral, LogChange.TRUE );
401     }
402 
403 
404     /**
405      * {@inheritDoc}
406      */
407     @Override
408     public void delete( Dn dn, boolean ignoreReferral, LogChange log ) throws LdapException
409     {
410         DeleteOperationContexttor/context/DeleteOperationContext.html#DeleteOperationContext">DeleteOperationContext deleteContext = new DeleteOperationContext( this, dn );
411 
412         deleteContext.setLogChange( log );
413         setReferralHandling( deleteContext, ignoreReferral );
414 
415         OperationManager operationManager = directoryService.getOperationManager();
416         operationManager.delete( deleteContext );
417     }
418 
419 
420     /**
421      * {@inheritDoc}
422      */
423     @Override
424     public LdapPrincipal getAnonymousPrincipal()
425     {
426         return anonymousPrincipal;
427     }
428 
429 
430     /**
431      * {@inheritDoc}
432      */
433     @Override
434     public LdapPrincipal getAuthenticatedPrincipal()
435     {
436         return authenticatedPrincipal;
437     }
438 
439 
440     /**
441      * {@inheritDoc}
442      */
443     @Override
444     public AuthenticationLevel getAuthenticationLevel()
445     {
446         return getEffectivePrincipal().getAuthenticationLevel();
447     }
448 
449 
450     /**
451      * {@inheritDoc}
452      */
453     @Override
454     public SocketAddress getClientAddress()
455     {
456         if ( ioSession != null )
457         {
458             return ioSession.getRemoteAddress();
459         }
460         else
461         {
462             return null;
463         }
464     }
465 
466 
467     /**
468      * {@inheritDoc}
469      */
470     @Override
471     public Set<Control> getControls()
472     {
473         // TODO Auto-generated method stub
474         return null;
475     }
476 
477 
478     /**
479      * {@inheritDoc}
480      */
481     @Override
482     public DirectoryService getDirectoryService()
483     {
484         return directoryService;
485     }
486 
487 
488     /**
489      * {@inheritDoc}
490      */
491     @Override
492     public LdapPrincipal getEffectivePrincipal()
493     {
494         if ( authorizedPrincipal == null )
495         {
496             return authenticatedPrincipal;
497         }
498 
499         return authorizedPrincipal;
500     }
501 
502 
503     /**
504      * {@inheritDoc}
505      */
506     @Override
507     public Set<OperationContext> getOutstandingOperations()
508     {
509         // TODO Auto-generated method stub
510         return null;
511     }
512 
513 
514     /**
515      * {@inheritDoc}
516      */
517     @Override
518     public SocketAddress getServiceAddress()
519     {
520         if ( ioSession != null )
521         {
522             return ioSession.getServiceAddress();
523         }
524         else
525         {
526             return null;
527         }
528     }
529 
530 
531     /**
532      * {@inheritDoc}
533      */
534     @Override
535     public boolean isConfidential()
536     {
537         // TODO Auto-generated method stub
538         return false;
539     }
540 
541 
542     /**
543      * {@inheritDoc}
544      */
545     @Override
546     public boolean isVirtual()
547     {
548         // TODO Auto-generated method stub
549         return true;
550     }
551 
552 
553     /**
554      * TODO - perhaps we should just use a flag that is calculated on creation
555      * of this session
556      * 
557      * @see org.apache.directory.server.core.api.CoreSession#isAdministrator()
558      */
559     @Override
560     public boolean isAdministrator()
561     {
562         String normName = getEffectivePrincipal().getName();
563 
564         return normName.equals( ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
565     }
566 
567 
568     /**
569      * TODO - this method impl does not check to see if the principal is in
570      * the administrators group - it only returns true of the principal is
571      * the actual admin user.  need to make it check groups.
572      * 
573      * TODO - perhaps we should just use a flag that is calculated on creation
574      * of this session
575      * 
576      * @see org.apache.directory.server.core.api.CoreSession#isAnAdministrator()
577      */
578     @Override
579     public boolean isAnAdministrator()
580     {
581         if ( isAdministrator() )
582         {
583             return true;
584         }
585 
586         // TODO fix this so it checks groups
587         return false;
588     }
589 
590 
591     /**
592      * {@inheritDoc}
593      */
594     @Override
595     public Cursor<Entry> list( Dn dn, AliasDerefMode aliasDerefMode,
596         String... returningAttributes ) throws LdapException
597     {
598         OperationManager operationManager = directoryService.getOperationManager();
599 
600         PresenceNode filter = new PresenceNode( objectClassAT );
601         SearchOperationContexttor/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( this, dn, SearchScope.ONELEVEL, filter,
602             returningAttributes );
603         searchContext.setAliasDerefMode( aliasDerefMode );
604 
605         return operationManager.search( searchContext );
606     }
607 
608 
609     /**
610      * {@inheritDoc}
611      */
612     @Override
613     public Entry lookup( Dn dn, String... attrIds ) throws LdapException
614     {
615         OperationManager operationManager = directoryService.getOperationManager();
616         LookupOperationContexttor/context/LookupOperationContext.html#LookupOperationContext">LookupOperationContext lookupContext = new LookupOperationContext( this, dn, attrIds );
617 
618         return operationManager.lookup( lookupContext );
619     }
620 
621 
622     /**
623      * {@inheritDoc}
624      */
625     @Override
626     public Entry lookup( Dn dn, Control[] controls, String... attrIds ) throws LdapException
627     {
628         OperationManager operationManager = directoryService.getOperationManager();
629         LookupOperationContexttor/context/LookupOperationContext.html#LookupOperationContext">LookupOperationContext lookupContext = new LookupOperationContext( this, dn, attrIds );
630 
631         if ( controls != null )
632         {
633             lookupContext.addRequestControls( controls );
634         }
635 
636         return operationManager.lookup( lookupContext );
637     }
638 
639 
640     /**
641      * {@inheritDoc}
642      */
643     @Override
644     public void modify( Dn dn, Modification... mods ) throws LdapException
645     {
646         modify( dn, Arrays.asList( mods ), LogChange.TRUE );
647     }
648 
649 
650     /**
651      * {@inheritDoc}
652      */
653     @Override
654     public void modify( Dn dn, List<Modification> mods ) throws LdapException
655     {
656         modify( dn, mods, LogChange.TRUE );
657     }
658 
659 
660     /**
661      * {@inheritDoc}
662      */
663     @Override
664     public void modify( Dn dn, List<Modification> mods, LogChange log ) throws LdapException
665     {
666         if ( mods == null )
667         {
668             return;
669         }
670 
671         List<Modification> serverModifications = new ArrayList<>( mods.size() );
672 
673         for ( Modification mod : mods )
674         {
675             serverModifications.add( new DefaultModification( directoryService.getSchemaManager(), mod ) );
676         }
677 
678         ModifyOperationContexttor/context/ModifyOperationContext.html#ModifyOperationContext">ModifyOperationContext modifyContext = new ModifyOperationContext( this, dn, serverModifications );
679 
680         modifyContext.setLogChange( log );
681 
682         OperationManager operationManager = directoryService.getOperationManager();
683         
684         operationManager.modify( modifyContext );
685     }
686 
687 
688     /**
689      * {@inheritDoc}
690      */
691     @Override
692     public void modify( Dn dn, List<Modification> mods, boolean ignoreReferral ) throws LdapException
693     {
694         modify( dn, mods, ignoreReferral, LogChange.TRUE );
695     }
696 
697 
698     /**
699      * {@inheritDoc}
700      */
701     @Override
702     public void modify( Dn dn, List<Modification> mods, boolean ignoreReferral, LogChange log ) throws LdapException
703     {
704         if ( mods == null )
705         {
706             return;
707         }
708 
709         List<Modification> serverModifications = new ArrayList<>( mods.size() );
710 
711         for ( Modification mod : mods )
712         {
713             serverModifications.add( new DefaultModification( directoryService.getSchemaManager(), mod ) );
714         }
715 
716         ModifyOperationContexttor/context/ModifyOperationContext.html#ModifyOperationContext">ModifyOperationContext modifyContext = new ModifyOperationContext( this, dn, serverModifications );
717 
718         setReferralHandling( modifyContext, ignoreReferral );
719         modifyContext.setLogChange( log );
720 
721         OperationManager operationManager = directoryService.getOperationManager();
722         operationManager.modify( modifyContext );
723     }
724 
725 
726     /**
727      * {@inheritDoc}
728      */
729     @Override
730     public void move( Dn dn, Dn newParent ) throws LdapException
731     {
732         move( dn, newParent, LogChange.TRUE );
733     }
734 
735 
736     /**
737      * {@inheritDoc}
738      */
739     @Override
740     public void move( Dn dn, Dn newParent, LogChange log ) throws LdapException
741     {
742         MoveOperationContextrceptor/context/MoveOperationContext.html#MoveOperationContext">MoveOperationContext moveContext = new MoveOperationContext( this, dn, newParent );
743         moveContext.setLogChange( log );
744 
745         OperationManager operationManager = directoryService.getOperationManager();
746         operationManager.move( moveContext );
747     }
748 
749 
750     /**
751      * {@inheritDoc}
752      */
753     @Override
754     public void move( Dn dn, Dn newParent, boolean ignoreReferral ) throws Exception
755     {
756         move( dn, newParent, ignoreReferral, LogChange.TRUE );
757     }
758 
759 
760     /**
761      * {@inheritDoc}
762      */
763     @Override
764     public void move( Dn dn, Dn newParent, boolean ignoreReferral, LogChange log ) throws LdapException
765     {
766         OperationManager operationManager = directoryService.getOperationManager();
767         MoveOperationContextrceptor/context/MoveOperationContext.html#MoveOperationContext">MoveOperationContext moveContext = new MoveOperationContext( this, dn, newParent );
768 
769         setReferralHandling( moveContext, ignoreReferral );
770         moveContext.setLogChange( log );
771 
772         operationManager.move( moveContext );
773     }
774 
775 
776     /**
777      * {@inheritDoc}
778      */
779     @Override
780     public void moveAndRename( Dn dn, Dn newParent, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
781     {
782         moveAndRename( dn, newParent, newRdn, deleteOldRdn, LogChange.TRUE );
783     }
784 
785 
786     /**
787      * {@inheritDoc}
788      */
789     @Override
790     public void moveAndRename( Dn dn, Dn newSuperiorDn, Rdn newRdn, boolean deleteOldRdn, LogChange log )
791         throws LdapException
792     {
793         MoveAndRenameOperationContextveAndRenameOperationContext.html#MoveAndRenameOperationContext">MoveAndRenameOperationContext moveAndRenameContext = new MoveAndRenameOperationContext( this, dn,
794             newSuperiorDn, newRdn, deleteOldRdn );
795 
796         moveAndRenameContext.setLogChange( log );
797 
798         OperationManager operationManager = directoryService.getOperationManager();
799         operationManager.moveAndRename( moveAndRenameContext );
800     }
801 
802 
803     /**
804      * {@inheritDoc}
805      */
806     @Override
807     public void moveAndRename( Dn dn, Dn newParent, Rdn newRdn, boolean deleteOldRdn, boolean ignoreReferral )
808         throws LdapException
809     {
810         moveAndRename( dn, newParent, newRdn, deleteOldRdn, ignoreReferral, LogChange.TRUE );
811     }
812 
813 
814     /**
815      * {@inheritDoc}
816      */
817     @Override
818     public void moveAndRename( Dn dn, Dn newParent, Rdn newRdn, boolean deleteOldRdn, boolean ignoreReferral,
819         LogChange log ) throws LdapException
820     {
821         OperationManager operationManager = directoryService.getOperationManager();
822         MoveAndRenameOperationContextveAndRenameOperationContext.html#MoveAndRenameOperationContext">MoveAndRenameOperationContext moveAndRenameContext = new MoveAndRenameOperationContext( this, dn, newParent,
823             newRdn, deleteOldRdn );
824 
825         moveAndRenameContext.setLogChange( log );
826         setReferralHandling( moveAndRenameContext, ignoreReferral );
827 
828         operationManager.moveAndRename( moveAndRenameContext );
829     }
830 
831 
832     /**
833      * {@inheritDoc}
834      */
835     @Override
836     public void rename( Dn dn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
837     {
838         rename( dn, newRdn, deleteOldRdn, LogChange.TRUE );
839     }
840 
841 
842     /**
843      * {@inheritDoc}
844      */
845     @Override
846     public void rename( Dn dn, Rdn newRdn, boolean deleteOldRdn, LogChange log ) throws LdapException
847     {
848         RenameOperationContexttor/context/RenameOperationContext.html#RenameOperationContext">RenameOperationContext renameContext = new RenameOperationContext( this, dn, newRdn, deleteOldRdn );
849 
850         renameContext.setLogChange( log );
851 
852         OperationManager operationManager = directoryService.getOperationManager();
853 
854         operationManager.rename( renameContext );
855     }
856 
857 
858     /**
859      * {@inheritDoc}
860      */
861     @Override
862     public void rename( Dn dn, Rdn newRdn, boolean deleteOldRdn, boolean ignoreReferral ) throws LdapException
863     {
864         rename( dn, newRdn, deleteOldRdn, ignoreReferral, LogChange.TRUE );
865     }
866 
867 
868     /**
869      * {@inheritDoc}
870      */
871     @Override
872     public void rename( Dn dn, Rdn newRdn, boolean deleteOldRdn, boolean ignoreReferral, LogChange log )
873         throws LdapException
874     {
875         OperationManager operationManager = directoryService.getOperationManager();
876         RenameOperationContexttor/context/RenameOperationContext.html#RenameOperationContext">RenameOperationContext renameContext = new RenameOperationContext( this, dn, newRdn, deleteOldRdn );
877 
878         renameContext.setLogChange( log );
879         setReferralHandling( renameContext, ignoreReferral );
880 
881         operationManager.rename( renameContext );
882     }
883 
884 
885     /**
886      * {@inheritDoc}
887      */
888     @Override
889     public Cursor<Entry> search( Dn dn, String filter ) throws LdapException
890     {
891         return search( dn, filter, true );
892     }
893 
894 
895     /**
896      * {@inheritDoc}
897      */
898     @Override
899     public Cursor<Entry> search( Dn dn, String filter, boolean ignoreReferrals ) throws LdapException
900     {
901         OperationManager operationManager = directoryService.getOperationManager();
902         ExprNode filterNode = null;
903 
904         try
905         {
906             filterNode = FilterParser.parse( directoryService.getSchemaManager(), filter );
907         }
908         catch ( ParseException pe )
909         {
910             throw new LdapInvalidSearchFilterException( pe.getMessage() );
911         }
912 
913         SearchOperationContexttor/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( this, dn, SearchScope.OBJECT, filterNode,
914             ( String ) null );
915         searchContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
916         setReferralHandling( searchContext, ignoreReferrals );
917 
918         return operationManager.search( searchContext );
919     }
920 
921 
922     /**
923      * {@inheritDoc}
924      */
925     @Override
926     public Cursor<Entry> search( Dn dn, SearchScope scope, ExprNode filter, AliasDerefMode aliasDerefMode,
927         String... returningAttributes ) throws LdapException
928     {
929         OperationManager operationManager = directoryService.getOperationManager();
930 
931         SearchOperationContexttor/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( this, dn, scope, filter, returningAttributes );
932         searchContext.setAliasDerefMode( aliasDerefMode );
933 
934         return operationManager.search( searchContext );
935     }
936 
937 
938     /**
939      * {@inheritDoc}
940      */
941     @Override
942     public boolean isAnonymous()
943     {
944         if ( ( authorizedPrincipal == null ) && ( authenticatedPrincipal == null ) )
945         {
946             return true;
947         }
948         else
949         {
950             return authenticatedPrincipal.getAuthenticationLevel() == AuthenticationLevel.NONE;
951         }
952     }
953 
954 
955     /**
956      * {@inheritDoc}
957      */
958     @Override
959     public boolean compare( CompareRequest compareRequest ) throws LdapException
960     {
961         CompareOperationContextr/context/CompareOperationContext.html#CompareOperationContext">CompareOperationContext compareContext = new CompareOperationContext( this, compareRequest );
962         OperationManager operationManager = directoryService.getOperationManager();
963         boolean result = false;
964         try
965         {
966             result = operationManager.compare( compareContext );
967         }
968         catch ( LdapException e )
969         {
970             compareRequest.getResultResponse().addAllControls( compareContext.getResponseControls() );
971             throw e;
972         }
973 
974         compareRequest.getResultResponse().addAllControls( compareContext.getResponseControls() );
975         return result;
976     }
977 
978 
979     /**
980      * {@inheritDoc}
981      */
982     @Override
983     public void delete( DeleteRequest deleteRequest ) throws LdapException
984     {
985         delete( deleteRequest, LogChange.TRUE );
986     }
987 
988 
989     /**
990      * {@inheritDoc}
991      */
992     @Override
993     public void delete( DeleteRequest deleteRequest, LogChange log ) throws LdapException
994     {
995         DeleteOperationContexttor/context/DeleteOperationContext.html#DeleteOperationContext">DeleteOperationContext deleteContext = new DeleteOperationContext( this, deleteRequest );
996 
997         deleteContext.setLogChange( log );
998 
999         OperationManager operationManager = directoryService.getOperationManager();
1000 
1001         try
1002         {
1003             operationManager.delete( deleteContext );
1004         }
1005         catch ( LdapException e )
1006         {
1007             deleteRequest.getResultResponse().addAllControls( deleteContext.getResponseControls() );
1008             throw e;
1009         }
1010 
1011         deleteRequest.getResultResponse().addAllControls( deleteContext.getResponseControls() );
1012     }
1013 
1014 
1015     /**
1016      * {@inheritDoc}
1017      */
1018     @Override
1019     public boolean exists( String dn ) throws LdapException
1020     {
1021         return exists( new Dn( dn ) );
1022     }
1023 
1024 
1025     /**
1026      * {@inheritDoc}
1027      */
1028     @Override
1029     public boolean exists( Dn dn ) throws LdapException
1030     {
1031         HasEntryOperationContextcontext/HasEntryOperationContext.html#HasEntryOperationContext">HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( this, dn );
1032         OperationManager operationManager = directoryService.getOperationManager();
1033 
1034         return operationManager.hasEntry( hasEntryContext );
1035     }
1036 
1037 
1038     /**
1039      * {@inheritDoc}
1040      */
1041     @Override
1042     public void modify( ModifyRequest modifyRequest ) throws LdapException
1043     {
1044         modify( modifyRequest, LogChange.TRUE );
1045     }
1046 
1047 
1048     /**
1049      * {@inheritDoc}
1050      */
1051     @Override
1052     public void modify( ModifyRequest modifyRequest, LogChange log ) throws LdapException
1053     {
1054         ModifyOperationContexttor/context/ModifyOperationContext.html#ModifyOperationContext">ModifyOperationContext modifyContext = new ModifyOperationContext( this, modifyRequest );
1055 
1056         modifyContext.setLogChange( log );
1057 
1058         OperationManager operationManager = directoryService.getOperationManager();
1059 
1060         try
1061         {
1062             operationManager.modify( modifyContext );
1063         }
1064         catch ( LdapException e )
1065         {
1066             modifyRequest.getResultResponse().addAllControls( modifyContext.getResponseControls() );
1067             throw e;
1068         }
1069 
1070         modifyRequest.getResultResponse().addAllControls( modifyContext.getResponseControls() );
1071     }
1072 
1073 
1074     /**
1075      * {@inheritDoc}
1076      */
1077     @Override
1078     public void move( ModifyDnRequest modifyDnRequest ) throws LdapException
1079     {
1080         move( modifyDnRequest, LogChange.TRUE );
1081     }
1082 
1083 
1084     /**
1085      * {@inheritDoc}
1086      */
1087     @Override
1088     public void move( ModifyDnRequest modifyDnRequest, LogChange log ) throws LdapException
1089     {
1090         MoveOperationContextrceptor/context/MoveOperationContext.html#MoveOperationContext">MoveOperationContext moveContext = new MoveOperationContext( this, modifyDnRequest );
1091 
1092         moveContext.setLogChange( log );
1093 
1094         OperationManager operationManager = directoryService.getOperationManager();
1095 
1096         try
1097         {
1098             operationManager.move( moveContext );
1099         }
1100         catch ( LdapException e )
1101         {
1102             modifyDnRequest.getResultResponse().addAllControls( moveContext.getResponseControls() );
1103             throw e;
1104         }
1105 
1106         modifyDnRequest.getResultResponse().addAllControls( moveContext.getResponseControls() );
1107     }
1108 
1109 
1110     /**
1111      * {@inheritDoc}
1112      */
1113     @Override
1114     public void moveAndRename( ModifyDnRequest modifyDnRequest ) throws LdapException
1115     {
1116         moveAndRename( modifyDnRequest, LogChange.TRUE );
1117     }
1118 
1119 
1120     /**
1121      * {@inheritDoc}
1122      */
1123     @Override
1124     public void moveAndRename( ModifyDnRequest modifyDnRequest, LogChange log ) throws LdapException
1125     {
1126         MoveAndRenameOperationContextveAndRenameOperationContext.html#MoveAndRenameOperationContext">MoveAndRenameOperationContext moveAndRenameContext = new MoveAndRenameOperationContext( this, modifyDnRequest );
1127 
1128         moveAndRenameContext.setLogChange( log );
1129 
1130         OperationManager operationManager = directoryService.getOperationManager();
1131 
1132         try
1133         {
1134             operationManager.moveAndRename( moveAndRenameContext );
1135         }
1136         catch ( LdapException e )
1137         {
1138             modifyDnRequest.getResultResponse().addAllControls( moveAndRenameContext.getResponseControls() );
1139             throw e;
1140         }
1141 
1142         modifyDnRequest.getResultResponse().addAllControls( moveAndRenameContext.getResponseControls() );
1143     }
1144 
1145 
1146     /**
1147      * {@inheritDoc}
1148      */
1149     @Override
1150     public void rename( ModifyDnRequest modifyDnRequest ) throws LdapException
1151     {
1152         rename( modifyDnRequest, LogChange.TRUE );
1153     }
1154 
1155 
1156     /**
1157      * {@inheritDoc}
1158      */
1159     @Override
1160     public void rename( ModifyDnRequest modifyDnRequest, LogChange log ) throws LdapException
1161     {
1162         RenameOperationContexttor/context/RenameOperationContext.html#RenameOperationContext">RenameOperationContext renameContext = new RenameOperationContext( this, modifyDnRequest );
1163 
1164         renameContext.setLogChange( log );
1165 
1166         OperationManager operationManager = directoryService.getOperationManager();
1167 
1168         try
1169         {
1170             operationManager.rename( renameContext );
1171         }
1172         catch ( LdapException e )
1173         {
1174             modifyDnRequest.getResultResponse().addAllControls( renameContext.getResponseControls() );
1175             throw e;
1176         }
1177 
1178         modifyDnRequest.getResultResponse().addAllControls( renameContext.getResponseControls() );
1179     }
1180 
1181 
1182     /**
1183      * {@inheritDoc}
1184      */
1185     @Override
1186     public Cursor<Entry> search( SearchRequest searchRequest ) throws LdapException
1187     {
1188         SearchOperationContexttor/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( this, searchRequest );
1189         searchContext.setSyncreplSearch( searchRequest.getControls().containsKey( SyncRequestValue.OID ) );
1190 
1191         OperationManager operationManager = directoryService.getOperationManager();
1192 
1193         // Check if we received serverside sort Control
1194         SortRequest sortControl = ( SortRequest ) searchRequest.getControls().get( SortRequest.OID );
1195 
1196         SortResponse sortRespCtrl = null;
1197 
1198         ResultResponse done = searchRequest.getResultResponse();
1199 
1200         LdapResult ldapResult = done.getLdapResult();
1201 
1202         if ( sortControl != null )
1203         {
1204             sortRespCtrl = canSort( sortControl, ldapResult, getDirectoryService().getSchemaManager() );
1205 
1206             if ( sortControl.isCritical() && ( sortRespCtrl.getSortResult() != SortResultCode.SUCCESS ) )
1207             {
1208                 ldapResult.setResultCode( ResultCodeEnum.UNAVAILABLE_CRITICAL_EXTENSION );
1209                 done.addControl( sortRespCtrl );
1210 
1211                 return new EmptyCursor<>();
1212             }
1213         }
1214 
1215         Cursor<Entry> cursor = null;
1216 
1217         try
1218         {
1219             cursor = operationManager.search( searchContext );
1220 
1221             if ( ( sortRespCtrl != null ) && ( sortRespCtrl.getSortResult() == SortResultCode.SUCCESS ) )
1222             {
1223                 cursor = sortResults( cursor, sortControl, getDirectoryService().getSchemaManager() );
1224             }
1225 
1226             // the below condition is to satisfy the scenario 6 in section 2 of rfc2891
1227             if ( sortRespCtrl != null )
1228             {
1229                 cursor.beforeFirst();
1230 
1231                 if ( !cursor.next() )
1232                 {
1233                     sortRespCtrl = null;
1234                 }
1235                 else
1236                 {
1237                     // move the cursor back
1238                     cursor.previous();
1239                 }
1240             }
1241         }
1242         catch ( LdapException e )
1243         {
1244             done.addAllControls( searchContext.getResponseControls() );
1245             throw e;
1246         }
1247         catch ( Exception e )
1248         {
1249             done.addAllControls( searchContext.getResponseControls() );
1250             throw new LdapException( e );
1251         }
1252         finally
1253         {
1254             // Don't close the transaction !!!
1255             LOG.debug( "Search done, the transaction is still opened" );
1256         }
1257 
1258         if ( sortRespCtrl != null )
1259         {
1260             done.addControl( sortRespCtrl );
1261         }
1262 
1263         done.addAllControls( searchContext.getResponseControls() );
1264 
1265         return cursor;
1266     }
1267 
1268 
1269     /**
1270      * {@inheritDoc}
1271      */
1272     @Override
1273     public void unbind() throws LdapException
1274     {
1275         UnbindOperationContexttor/context/UnbindOperationContext.html#UnbindOperationContext">UnbindOperationContext unbindContext = new UnbindOperationContext( this );
1276 
1277         OperationManager operationManager = directoryService.getOperationManager();
1278         operationManager.unbind( unbindContext );
1279     }
1280 
1281 
1282     /**
1283      * {@inheritDoc}
1284      */
1285     @Override
1286     public void unbind( UnbindRequest unbindRequest ) throws LdapException
1287     {
1288         UnbindOperationContexttor/context/UnbindOperationContext.html#UnbindOperationContext">UnbindOperationContext unbindContext = new UnbindOperationContext( this, unbindRequest );
1289 
1290         OperationManager operationManager = directoryService.getOperationManager();
1291         operationManager.unbind( unbindContext );
1292     }
1293 
1294 
1295     /**
1296      * Checks if the requested search results can be sorted
1297      * 
1298      * @param sortControl the sort control
1299      * @param ldapResult the refrence to the LDAP result of the ongoing search operation
1300      * @param session the current session
1301      * @return a sort response control
1302      */
1303     private SortResponse canSort( SortRequest sortControl, LdapResult ldapResult, SchemaManager schemaManager )
1304     {
1305         SortResponse resp = new SortResponseImpl();
1306 
1307         List<SortKey> keys = sortControl.getSortKeys();
1308 
1309         // only ONE key is supported by the server for now
1310         if ( keys.size() > 1 )
1311         {
1312             ldapResult.setDiagnosticMessage( "Cannot sort results based on more than one attribute" );
1313             resp.setSortResult( SortResultCode.UNWILLINGTOPERFORM );
1314             return resp;
1315         }
1316 
1317         SortKey sk = keys.get( 0 );
1318 
1319         AttributeType at = schemaManager.getAttributeType( sk.getAttributeTypeDesc() );
1320 
1321         if ( at == null )
1322         {
1323             ldapResult.setDiagnosticMessage( "No attribute with the name " + sk.getAttributeTypeDesc()
1324                 + " exists in the server's schema" );
1325             resp.setSortResult( SortResultCode.NOSUCHATTRIBUTE );
1326             resp.setAttributeName( sk.getAttributeTypeDesc() );
1327             return resp;
1328         }
1329 
1330         String mrOid = sk.getMatchingRuleId();
1331 
1332         if ( mrOid != null )
1333         {
1334             MatchingRule mr = at.getOrdering();
1335 
1336             if ( ( mr != null ) && ( !mrOid.equals( mr.getOid() ) ) )
1337             {
1338                 ldapResult.setDiagnosticMessage( "Given matchingrule " + mrOid
1339                     + " is not applicable for the attribute " + sk.getAttributeTypeDesc() );
1340                 resp.setSortResult( SortResultCode.INAPPROPRIATEMATCHING );
1341                 resp.setAttributeName( sk.getAttributeTypeDesc() );
1342                 return resp;
1343             }
1344 
1345             try
1346             {
1347                 schemaManager.lookupComparatorRegistry( mrOid );
1348             }
1349             catch ( LdapException e )
1350             {
1351                 ldapResult.setDiagnosticMessage( "Given matchingrule " + mrOid + " is not supported" );
1352                 resp.setSortResult( SortResultCode.INAPPROPRIATEMATCHING );
1353                 resp.setAttributeName( sk.getAttributeTypeDesc() );
1354                 return resp;
1355             }
1356         }
1357         else
1358         {
1359             MatchingRule mr = at.getOrdering();
1360 
1361             if ( mr == null )
1362             {
1363                 mr = at.getEquality();
1364             }
1365 
1366             ldapResult.setDiagnosticMessage( "Matchingrule is required for sorting by the attribute "
1367                 + sk.getAttributeTypeDesc() );
1368             resp.setSortResult( SortResultCode.INAPPROPRIATEMATCHING );
1369             resp.setAttributeName( sk.getAttributeTypeDesc() );
1370 
1371             if ( mr == null )
1372             {
1373                 return resp;
1374             }
1375 
1376             try
1377             {
1378                 schemaManager.lookupComparatorRegistry( mr.getOid() );
1379             }
1380             catch ( LdapException e )
1381             {
1382                 return resp;
1383             }
1384         }
1385 
1386         resp.setSortResult( SortResultCode.SUCCESS );
1387 
1388         return resp;
1389     }
1390 
1391 
1392     /**
1393      * Sorts the entries based on the given sortkey and returns the cursor
1394      * 
1395      * @param unsortedEntries the cursor containing un-sorted entries
1396      * @param control the sort control
1397      * @param schemaManager schema manager
1398      * @return a cursor containing sorted entries
1399      * @throws CursorException
1400      * @throws LdapException
1401      * @throws IOException
1402      * @throws KeyNotFoundException 
1403      */
1404     private Cursor<Entry> sortResults( Cursor<Entry> unsortedEntries, SortRequest control, SchemaManager schemaManager )
1405         throws CursorException, LdapException, IOException
1406     {
1407         unsortedEntries.beforeFirst();
1408 
1409         Entry first = null;
1410 
1411         if ( unsortedEntries.next() )
1412         {
1413             first = unsortedEntries.get();
1414         }
1415 
1416         if ( !unsortedEntries.next() )
1417         {
1418             unsortedEntries.beforeFirst();
1419 
1420             return unsortedEntries;
1421         }
1422 
1423         SortKey sk = control.getSortKeys().get( 0 );
1424 
1425         AttributeType at = schemaManager.getAttributeType( sk.getAttributeTypeDesc() );
1426 
1427         SortedEntryComparatorortedEntryComparator.html#SortedEntryComparator">SortedEntryComparator comparator = new SortedEntryComparator( at, sk.getMatchingRuleId(), sk.isReverseOrder(),
1428             schemaManager );
1429 
1430         SortedEntrySerializeredEntrySerializer.html#SortedEntrySerializer">SortedEntrySerializer keySerializer = new SortedEntrySerializer();
1431         SortedEntrySerializer.setSchemaManager( schemaManager );
1432         
1433         File file = null;
1434         
1435         try 
1436         {
1437             file = Files.createTempFile( "replica", ".sorted-data" ).toFile();    // see DIRSERVER-2007
1438         } 
1439         catch ( IOException e ) 
1440         {
1441             // see DIRSERVER-2091
1442             LOG.error( "Error creating temp file in directory {} for sorting: {}",  
1443                 System.getProperty( "java.io.tmpdir" ),  e.getMessage(), e );
1444             throw e;
1445         }
1446 
1447         BaseRecordManager recMan = new BaseRecordManager( file.getAbsolutePath() );
1448 
1449         jdbm.btree.BTree<Entry, String> btree = new jdbm.btree.BTree<>( recMan, comparator, keySerializer, NullStringSerializer.INSTANCE );
1450         
1451 
1452         btree.insert( first, "", false );
1453 
1454         // at this stage the cursor will be _on_ the next element, so read it
1455         btree.insert( unsortedEntries.get(), "", false );
1456 
1457         while ( unsortedEntries.next() )
1458         {
1459             Entry entry = unsortedEntries.get();
1460             btree.insert( entry, "", false );
1461         }
1462 
1463         unsortedEntries.close();
1464 
1465         return new SortedEntryCursor( btree, recMan, file );
1466     }
1467 
1468 
1469     /**
1470      * {@inheritDoc}
1471      */
1472     @Override
1473     public boolean isPwdMustChange() 
1474     {
1475         return pwdMustChange;
1476     }
1477 
1478 
1479     /**
1480      * {@inheritDoc}
1481      */
1482     @Override
1483     public void setPwdMustChange( boolean pwdMustChange ) 
1484     {
1485         this.pwdMustChange = pwdMustChange;
1486     }
1487 
1488     
1489     /**
1490      * {@inheritDoc}
1491      */
1492     @Override
1493     public boolean hasSessionTransaction()
1494     {
1495         return hasSessionTransaction;
1496     }
1497     
1498     
1499     /**
1500      * {@inheritDoc}
1501      */
1502     @Override
1503     public long beginSessionTransaction()
1504     {
1505         hasSessionTransaction = true;
1506         
1507         return transactionId.getAndIncrement();
1508     }
1509     
1510     
1511     /**
1512      * {@inheritDoc}
1513      */
1514     @Override
1515     public void endSessionTransaction( boolean commit ) throws IOException
1516     {
1517         if ( commit )
1518         {
1519             for ( Map.Entry<String, PartitionTxn> partitionTxn : transactionMap.entrySet() )
1520             {
1521                 partitionTxn.getValue().commit();
1522             }
1523         }
1524         else
1525         {
1526             for ( Map.Entry<String, PartitionTxn> partitionTxn : transactionMap.entrySet() )
1527             {
1528                 partitionTxn.getValue().abort();
1529             }
1530         }
1531         
1532         hasSessionTransaction = false;
1533     }
1534 
1535 
1536     /**
1537      * {@inheritDoc}
1538      */
1539     @Override
1540     public PartitionTxn getTransaction( Partition partition ) 
1541     {
1542         return transactionMap.get( partition.getId() );
1543     }
1544 
1545 
1546     /**
1547      * {@inheritDoc}
1548      */
1549     @Override
1550     public void addTransaction( Partition partition, PartitionTxn transaction )
1551     {
1552         if ( !transactionMap.containsKey( partition.getId() ) )
1553         {
1554             transactionMap.put( partition.getId(), transaction );
1555         }
1556     }
1557 }