View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.client.methods;
29  
30  import java.io.IOException;
31  import java.net.URI;
32  import java.util.concurrent.locks.Lock;
33  import java.util.concurrent.locks.ReentrantLock;
34  
35  import org.apache.http.annotation.NotThreadSafe;
36  
37  import org.apache.http.ProtocolVersion;
38  import org.apache.http.RequestLine;
39  import org.apache.http.client.utils.CloneUtils;
40  import org.apache.http.conn.ClientConnectionRequest;
41  import org.apache.http.conn.ConnectionReleaseTrigger;
42  import org.apache.http.message.AbstractHttpMessage;
43  import org.apache.http.message.BasicRequestLine;
44  import org.apache.http.message.HeaderGroup;
45  import org.apache.http.params.HttpParams;
46  import org.apache.http.params.HttpProtocolParams;
47  
48  /**
49   * Basic implementation of an HTTP request that can be modified. Methods of the
50   * {@link AbortableHttpRequest} interface implemented by this class are thread safe.
51   *
52   * @since 4.0
53   */
54  @NotThreadSafe
55  public abstract class HttpRequestBase extends AbstractHttpMessage
56      implements HttpUriRequest, AbortableHttpRequest, Cloneable {
57  
58      private Lock abortLock;
59      private volatile boolean aborted;
60  
61      private URI uri;
62      private ClientConnectionRequest connRequest;
63      private ConnectionReleaseTrigger releaseTrigger;
64  
65      public HttpRequestBase() {
66          super();
67          this.abortLock = new ReentrantLock();
68      }
69  
70      public abstract String getMethod();
71  
72      public ProtocolVersion getProtocolVersion() {
73          return HttpProtocolParams.getVersion(getParams());
74      }
75  
76      /**
77       * Returns the original request URI.
78       * <p>
79       * Please note URI remains unchanged in the course of request execution and
80       * is not updated if the request is redirected to another location.
81       */
82      public URI getURI() {
83          return this.uri;
84      }
85  
86      public RequestLine getRequestLine() {
87          String method = getMethod();
88          ProtocolVersion ver = getProtocolVersion();
89          URI uri = getURI();
90          String uritext = null;
91          if (uri != null) {
92              uritext = uri.toASCIIString();
93          }
94          if (uritext == null || uritext.length() == 0) {
95              uritext = "/";
96          }
97          return new BasicRequestLine(method, uritext, ver);
98      }
99  
100     public void setURI(final URI uri) {
101         this.uri = uri;
102     }
103 
104     public void setConnectionRequest(final ClientConnectionRequest connRequest)
105             throws IOException {
106         if (this.aborted) {
107             throw new IOException("Request already aborted");
108         }
109         this.abortLock.lock();
110         try {
111             this.connRequest = connRequest;
112         } finally {
113             this.abortLock.unlock();
114         }
115     }
116 
117     public void setReleaseTrigger(final ConnectionReleaseTrigger releaseTrigger)
118             throws IOException {
119         if (this.aborted) {
120             throw new IOException("Request already aborted");
121         }
122         this.abortLock.lock();
123         try {
124             this.releaseTrigger = releaseTrigger;
125         } finally {
126             this.abortLock.unlock();
127         }
128     }
129 
130     private void cleanup() {
131         if (this.connRequest != null) {
132             this.connRequest.abortRequest();
133             this.connRequest = null;
134         }
135         if (this.releaseTrigger != null) {
136             try {
137                 this.releaseTrigger.abortConnection();
138             } catch (IOException ex) {
139             }
140             this.releaseTrigger = null;
141         }
142     }
143 
144     public void abort() {
145         if (this.aborted) {
146             return;
147         }
148         this.abortLock.lock();
149         try {
150             this.aborted = true;
151             cleanup();
152         } finally {
153             this.abortLock.unlock();
154         }
155     }
156 
157     public boolean isAborted() {
158         return this.aborted;
159     }
160 
161     /**
162      * Resets internal state of the request making it reusable.
163      *
164      * @since 4.2
165      */
166     public void reset() {
167         this.abortLock.lock();
168         try {
169             cleanup();
170             this.aborted = false;
171         } finally {
172             this.abortLock.unlock();
173         }
174     }
175 
176     /**
177      * A convenience method to simplify migration from HttpClient 3.1 API. This method is
178      * equivalent to {@link #reset()}.
179      *
180      * @since 4.2
181      */
182     public void releaseConnection() {
183         reset();
184     }
185 
186     @Override
187     public Object clone() throws CloneNotSupportedException {
188         HttpRequestBase clone = (HttpRequestBase) super.clone();
189         clone.abortLock = new ReentrantLock();
190         clone.aborted = false;
191         clone.releaseTrigger = null;
192         clone.connRequest = null;
193         clone.headergroup = (HeaderGroup) CloneUtils.clone(this.headergroup);
194         clone.params = (HttpParams) CloneUtils.clone(this.params);
195         return clone;
196     }
197 
198     @Override
199     public String toString() {
200         return getMethod() + " " + getURI() + " " + getProtocolVersion();
201     }    
202 
203 }