View Javadoc
1   /* 
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   *
14   */
15  
16  package org.esigate.test.conn;
17  
18  import java.io.IOException;
19  import java.util.concurrent.TimeUnit;
20  import java.util.concurrent.atomic.AtomicInteger;
21  
22  import org.apache.http.HttpClientConnection;
23  import org.apache.http.HttpConnectionMetrics;
24  import org.apache.http.HttpEntityEnclosingRequest;
25  import org.apache.http.HttpRequest;
26  import org.apache.http.HttpResponse;
27  import org.apache.http.conn.ConnectionRequest;
28  import org.apache.http.conn.HttpClientConnectionManager;
29  import org.apache.http.conn.routing.HttpRoute;
30  import org.apache.http.protocol.HttpContext;
31  import org.esigate.HttpErrorPage;
32  
33  public class MockConnectionManager implements HttpClientConnectionManager {
34      private final AtomicInteger openConnections = new AtomicInteger(0);
35      private IResponseHandler responseHandler;
36      private HttpRequest lastSentRequest;
37      private long sleep = 0L;
38  
39      private void sleep() {
40          if (sleep > 0) {
41              try {
42                  Thread.sleep(sleep);
43              } catch (InterruptedException e) {
44                  throw new RuntimeException(e);
45              }
46          }
47      }
48  
49      @Override
50      public ConnectionRequest requestConnection(HttpRoute route, Object state) {
51          return new ConnectionRequest() {
52  
53              @Override
54              public boolean cancel() {
55                  return false;
56              }
57  
58              @Override
59              public HttpClientConnection get(long timeout, TimeUnit tunit) {
60                  openConnections.incrementAndGet();
61                  return new HttpClientConnection() {
62                      private boolean open = true;
63                      private HttpRequest request;
64  
65                      @Override
66                      public void shutdown() {
67                          close();
68                      }
69  
70                      @Override
71                      public void setSocketTimeout(int timeout) {
72                          // Nothing to do
73                      }
74  
75                      @Override
76                      public boolean isStale() {
77                          return !open;
78                      }
79  
80                      @Override
81                      public boolean isOpen() {
82                          return open;
83                      }
84  
85                      @Override
86                      public int getSocketTimeout() {
87                          return 0;
88                      }
89  
90                      @Override
91                      public HttpConnectionMetrics getMetrics() {
92                          return null;
93                      }
94  
95                      @Override
96                      public void close() {
97                          openConnections.decrementAndGet();
98                          open = false;
99                      }
100 
101                     @Override
102                     public void sendRequestHeader(HttpRequest request) {
103                         lastSentRequest = request;
104                         this.request = request;
105                     }
106 
107                     @Override
108                     public void sendRequestEntity(HttpEntityEnclosingRequest request) {
109                         lastSentRequest = request;
110                         this.request = request;
111                     }
112 
113                     @Override
114                     public HttpResponse receiveResponseHeader() {
115                         sleep();
116                         return execute(this.request);
117                     }
118 
119                     @Override
120                     public void receiveResponseEntity(HttpResponse response) {
121                         // Nothing to do
122                     }
123 
124                     @Override
125                     public boolean isResponseAvailable(int timeout) {
126                         return true;
127                     }
128 
129                     @Override
130                     public void flush() {
131                         // Nothing to do
132                     }
133                 };
134             }
135         };
136     }
137 
138     @Override
139     public void releaseConnection(HttpClientConnection conn, Object newState, long validDuration, TimeUnit timeUnit) {
140         try {
141             conn.close();
142         } catch (IOException e) {
143             throw new RuntimeException(e);
144         }
145     }
146 
147     @Override
148     public void closeIdleConnections(long idletime, TimeUnit tunit) {
149         // Nothing to do
150     }
151 
152     @Override
153     public void closeExpiredConnections() {
154         // Nothing to do
155     }
156 
157     @Override
158     public void shutdown() {
159         if (openConnections.get() > 0)
160             throw new RuntimeException("Some connections were not released!");
161     }
162 
163     public HttpRequest getSentRequest() {
164         return lastSentRequest;
165     }
166 
167     /**
168      * Set the HttpResponse that will always be returned when calling the backend.
169      * 
170      * @param response
171      */
172     public void setResponse(final HttpResponse response) {
173         setResponseHandler(new IResponseHandler() {
174             @Override
175             public HttpResponse execute(HttpRequest request) {
176                 return response;
177             }
178         });
179     }
180 
181     /**
182      * Set a custom response handler. This allows to control and inject all responses from backend.
183      * 
184      * @param responseHandler
185      */
186     public void setResponseHandler(IResponseHandler responseHandler) {
187         this.responseHandler = responseHandler;
188     }
189 
190     public HttpResponse execute(HttpRequest request) {
191         try {
192             return this.responseHandler.execute(request);
193         } catch (IOException e) {
194             return HttpErrorPage.generateHttpResponse(e);
195         }
196     }
197 
198     public final boolean hasOpenConnections() {
199         return openConnections.get() > 0;
200     }
201 
202     @Override
203     public void connect(HttpClientConnection conn, HttpRoute route, int connectTimeout, HttpContext context) {
204         if (this.responseHandler instanceof IResponseHandler2) {
205             ((IResponseHandler2) this.responseHandler).connect(conn, route, connectTimeout, context);
206         }
207     }
208 
209     @Override
210     public void upgrade(HttpClientConnection conn, HttpRoute route, HttpContext context) {
211         // Nothing to do
212     }
213 
214     @Override
215     public void routeComplete(HttpClientConnection conn, HttpRoute route, HttpContext context) {
216         // Nothing to do
217     }
218 
219 }