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 *    https://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.ldap.client.api.future;
021
022
023import java.util.concurrent.ExecutionException;
024import java.util.concurrent.Future;
025import java.util.concurrent.TimeUnit;
026import java.util.concurrent.TimeoutException;
027
028
029/**
030 * A Future to manage StartTLS handshake
031 *
032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
033 */
034public class HandshakeFuture implements Future<Boolean>
035{
036    /** A flag set to TRUE when the handshake has been completed */
037    private volatile boolean done = false;
038
039    /** flag to determine if this future is cancelled */
040    protected boolean cancelled = false;
041
042    /**
043     * Creates a new instance of HandshakeFuture.
044     */
045    public HandshakeFuture()
046    {
047        // Nothing to initialize...
048    }
049
050
051    /**
052     * Cancel the Future
053     *
054     */
055    public synchronized void cancel()
056    {
057        // set the cancel flag first
058        cancelled = true;
059
060        // Notify the future
061        notifyAll();
062    }
063
064
065    /**
066     * Set the Future to done when the TLS handshake has completed
067     */
068    public synchronized void secured()
069    {
070        done = true;
071
072        notifyAll();
073    }
074
075
076    /**
077     * {@inheritDoc}
078     */
079    @Override
080    public synchronized boolean cancel( boolean mayInterruptIfRunning )
081    {
082        if ( cancelled )
083        {
084            return cancelled;
085        }
086
087        // set the cancel flag first
088        cancelled = true;
089
090        // Notify the future
091        notifyAll();
092
093        return cancelled;
094    }
095
096
097    /**
098     * {@inheritDoc}
099     */
100    @Override
101    public synchronized Boolean get() throws InterruptedException, ExecutionException
102    {
103        while ( !done && !cancelled )
104        {
105            wait();
106        }
107
108        return done;
109    }
110
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    public synchronized Boolean get( long timeout, TimeUnit unit )
117        throws InterruptedException, ExecutionException, TimeoutException
118    {
119        // no need to wait if already done or cancelled
120        if ( !done && !cancelled )
121        {
122            wait( unit.toMillis( timeout ) );
123        }
124
125        return done;
126    }
127
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public boolean isCancelled()
134    {
135        return cancelled;
136    }
137
138
139    /**
140     * {@inheritDoc}
141     */
142    @Override
143    public boolean isDone()
144    {
145        return done;
146    }
147
148
149    /**
150     * {@inheritDoc}
151     */
152    @Override
153    public String toString()
154    {
155        StringBuilder sb = new StringBuilder();
156    
157        sb.append( "HandshakeFuture, completed: " ).append( done ).append( ", cancelled: " ).append( cancelled );
158    
159        return sb.toString();
160    }
161}