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.shared.ldap.cursor;
021    
022    
023    /**
024     * A basic ClosureMonitor that simply uses a boolean for state and a cause 
025     * exception.
026     * 
027     * Note that we consciously chose not to synchronize close() operations with
028     * checks to see if the monitor state is closed because it costs to 
029     * synchronize and it's OK for the Cursor not to stop immediately when close()
030     * is called.
031     *
032     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
033     * @version $Rev$, $Date$
034     */
035    public class DefaultClosureMonitor implements ClosureMonitor
036    {
037        /** Tells if the monitor is closed or not */
038        private boolean closed;
039        
040        /** If we get an exception, the cause is stored in this variable */
041        private Exception cause;
042    
043        
044        /**
045         * {@inheritDoc}
046         */
047        public final void close()
048        {
049            // state check needed to "try" not to overwrite exception (lack of 
050            // synchronization may still allow overwriting but who cares that much
051            if ( ! closed )
052            {
053                // not going to sync because who cares if it takes a little longer 
054                // to stop but we need to set cause before toggling closed state 
055                // or else check for closure can throw null cause 
056                cause = new CursorClosedException();
057                closed = true;
058            }
059        }
060    
061    
062        /**
063         * {@inheritDoc}
064         */
065        public final void close( final String cause )
066        {
067            // state check needed to "try" not to overwrite exception (lack of 
068            // synchronization may still allow overwriting but who cares that much
069            if ( ! closed )
070            {
071                // not going to sync because who cares if it takes a little longer 
072                // to stop but we need to set cause before toggling closed state 
073                // or else check for closure can throw null cause 
074                this.cause = new CursorClosedException( cause );
075                closed = true;
076            }
077        }
078    
079    
080        /**
081         * {@inheritDoc}
082         */
083        public final void close( final Exception cause )
084        {
085            // state check needed to "try" not to overwrite exception (lack of 
086            // synchronization may still allow overwriting but who cares that much
087            if ( ! closed )
088            {
089                // not going to sync because who cares if it takes a little longer 
090                // to stop but we need to set cause before toggling closed state 
091                // or else check for closure can throw null cause 
092                this.cause = cause;
093                closed = true;
094            }
095        }
096    
097    
098        /**
099         * {@inheritDoc}
100         */
101        public final Exception getCause()
102        {
103            return cause;
104        }
105    
106    
107        /**
108         * {@inheritDoc}
109         */
110        public final boolean isClosed()
111        {
112            return closed;
113        }
114    
115    
116        /**
117         * {@inheritDoc}
118         */
119        public void checkNotClosed() throws Exception
120        {
121            // lack of synchronization may cause pass but eventually it will work
122            if ( closed )
123            {
124                throw cause;
125            }
126        }
127    }