001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.client.methods;
028
029import java.io.IOException;
030import java.util.concurrent.atomic.AtomicBoolean;
031import java.util.concurrent.atomic.AtomicReference;
032
033import org.apache.http.HttpRequest;
034import org.apache.http.client.utils.CloneUtils;
035import org.apache.http.concurrent.Cancellable;
036import org.apache.http.conn.ClientConnectionRequest;
037import org.apache.http.conn.ConnectionReleaseTrigger;
038import org.apache.http.message.AbstractHttpMessage;
039
040@SuppressWarnings("deprecation")
041public abstract class AbstractExecutionAwareRequest extends AbstractHttpMessage implements
042        HttpExecutionAware, AbortableHttpRequest, Cloneable, HttpRequest {
043
044    private final AtomicBoolean aborted;
045    private final AtomicReference<Cancellable> cancellableRef;
046
047    protected AbstractExecutionAwareRequest() {
048        super();
049        this.aborted = new AtomicBoolean(false);
050        this.cancellableRef = new AtomicReference<Cancellable>(null);
051    }
052
053    @Override
054    @Deprecated
055    public void setConnectionRequest(final ClientConnectionRequest connRequest) {
056        setCancellable(new Cancellable() {
057
058            @Override
059            public boolean cancel() {
060                connRequest.abortRequest();
061                return true;
062            }
063
064        });
065    }
066
067    @Override
068    @Deprecated
069    public void setReleaseTrigger(final ConnectionReleaseTrigger releaseTrigger) {
070        setCancellable(new Cancellable() {
071
072            @Override
073            public boolean cancel() {
074                try {
075                    releaseTrigger.abortConnection();
076                    return true;
077                } catch (final IOException ex) {
078                    return false;
079                }
080            }
081
082        });
083    }
084
085    @Override
086    public void abort() {
087        if (this.aborted.compareAndSet(false, true)) {
088            final Cancellable cancellable = this.cancellableRef.getAndSet(null);
089            if (cancellable != null) {
090                cancellable.cancel();
091            }
092        }
093    }
094
095    @Override
096    public boolean isAborted() {
097        return this.aborted.get();
098    }
099
100    /**
101     * @since 4.2
102     */
103    @Override
104    public void setCancellable(final Cancellable cancellable) {
105        if (!this.aborted.get()) {
106            this.cancellableRef.set(cancellable);
107        }
108    }
109
110    @Override
111    public Object clone() throws CloneNotSupportedException {
112        final AbstractExecutionAwareRequest clone = (AbstractExecutionAwareRequest) super.clone();
113        clone.headergroup = CloneUtils.cloneObject(this.headergroup);
114        clone.params = CloneUtils.cloneObject(this.params);
115        return clone;
116    }
117
118    /**
119     * @since 4.2
120     */
121    public void completed() {
122        this.cancellableRef.set(null);
123    }
124
125    /**
126     * Resets internal state of the request making it reusable.
127     *
128     * @since 4.2
129     */
130    public void reset() {
131        final Cancellable cancellable = this.cancellableRef.getAndSet(null);
132        if (cancellable != null) {
133            cancellable.cancel();
134        }
135        this.aborted.set(false);
136    }
137
138}