source: trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitorRemoteConnection.java @ 1991

Last change on this file since 1991 was 1991, checked in by pharms, 9 years ago
  • added ordering id for requests and responses
File size: 6.5 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.httpmonitor.proxy;
16
17import java.util.HashMap;
18import java.util.Map;
19import java.util.logging.Level;
20
21import org.eclipse.jetty.client.HttpClient;
22import org.eclipse.jetty.client.api.Request;
23import org.eclipse.jetty.client.api.Response.CompleteListener;
24import org.eclipse.jetty.client.api.Result;
25import org.eclipse.jetty.util.thread.QueuedThreadPool;
26
27import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
28import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
29import de.ugoe.cs.util.console.Console;
30
31/**
32 * <p>
33 * This is a base class that combines common implementations required for connecting to a central
34 * HTTP monitoring server. The class allows for sending HTTP requests to the central server and
35 * waiting for the asynchronous response.
36 * </p>
37 *
38 * @author Patrick Harms
39 */
40public abstract class HttpMonitorRemoteConnection implements CompleteListener, HttpMonitorComponent
41{
42   
43    /**
44     * <p>
45     * the HTTP client used internally to send data to the central server
46     * </p>
47     */
48    private HttpClient httpClient;
49   
50    /**
51     * <p>
52     * the host name of the central server
53     * </p>
54     */
55    private String httpMonitorServer;
56   
57    /**
58     * <p>
59     * the port of the central server
60     * </p>
61     */
62    private int httpMonitorPort;
63
64    /**
65     * <p>
66     * a map of requests send to the central server and the corresponding result.
67     * Initially, the result mapped to a request is null until the result is received.
68     * </p>
69     */
70    private Map<Request, Result> openRequests = new HashMap<>();
71   
72    /**
73     * <p>
74     * initializes the exchange handler with the host and port of the central server
75     * </p>
76     *
77     * @param httpMonitorServer the host name of the central server
78     * @param httpMonitorPort   the port of the central server
79     */
80    public HttpMonitorRemoteConnection(String httpMonitorServer, int httpMonitorPort) {
81        this.httpMonitorServer = httpMonitorServer;
82        this.httpMonitorPort = httpMonitorPort;
83    }
84
85    /* (non-Javadoc)
86     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#init()
87     */
88    @Override
89    public void init() throws IllegalStateException, HttpMonitorException {
90        httpClient = createHttpClient();
91    }
92
93    /* (non-Javadoc)
94     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#start()
95     */
96    @Override
97    public void start() throws IllegalStateException, HttpMonitorException {
98        try {
99            httpClient.start();
100            httpClient.getContentDecoderFactories().clear();
101        }
102        catch (Exception e) {
103            throw new HttpMonitorException("could not start client for HTTP-Monitor", e);
104        }
105    }
106
107    /* (non-Javadoc)
108     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#stop()
109     */
110    @Override
111    public void stop() {
112        if (httpClient != null) {
113            try {
114                httpClient.stop();
115            }
116            catch (Exception e) {
117                Console.traceln(Level.WARNING, "could not stop client for HTTP-Monitor");
118                Console.logException(e);
119            }
120        }
121       
122        httpClient = null;
123    }
124
125    /**
126     * <p>
127     * creates a new request that can be used by subclasses to send something to the central server
128     * </p>
129     *
130     * @return as described
131     */
132    protected Request newRequest() {
133        return httpClient.newRequest(httpMonitorServer, httpMonitorPort);
134    }
135
136    /**
137     * <p>
138     * used to send a request to the central server. The request is stored internally to be able
139     * to wait for the result.
140     * </p>
141     *
142     * @param httpMonitorRequest the request to be sent to the central server
143     */
144    protected synchronized void sendRequest(Request httpMonitorRequest) {
145        openRequests.put(httpMonitorRequest, null);
146        httpMonitorRequest.send(this);
147    }
148
149    /**
150     * <p>
151     * used to synchronously wait for the result of a given request.
152     * </p>
153     *
154     * @param httpMonitorRequest the request for which the result shall be waited for
155     *
156     * @return the result of the request or null, if no result was received after 30 seconds
157     */
158    protected synchronized Result getResult(Request httpMonitorRequest) {
159
160        try {
161            // wait for the result of the request to be added to the map asynchronously
162            int count = 30;
163            while (openRequests.containsKey(httpMonitorRequest) &&
164                   (openRequests.get(httpMonitorRequest) == null))
165            {
166                this.wait(1000);
167               
168                if (--count == 0) {
169                    // after 30 seconds, cancel the sending of the request
170                    openRequests.remove(httpMonitorRequest);
171                    break;
172                }
173            }
174        }
175        catch (InterruptedException e) {
176            // ignore, as this may only happen on system shutdown
177        }
178
179        return openRequests.get(httpMonitorRequest);
180    }
181
182    /* (non-Javadoc)
183     * @see org.eclipse.jetty.client.api.Response.CompleteListener#onComplete(Result)
184     */
185    @Override
186    public synchronized void onComplete(Result result) {
187        openRequests.put(result.getRequest(), result);
188        this.notify();
189    }
190
191    /**
192     * <p>
193     * convenience method to create an initialize the utilized HTTP client
194     * </p>
195     */
196    private HttpClient createHttpClient() {
197        HttpClient client = new HttpClient();
198       
199        QueuedThreadPool executor = new QueuedThreadPool(10);
200        executor.setName("HttpMonitorClients");
201        client.setExecutor(executor);
202
203        client.setMaxConnectionsPerDestination(10000);
204        client.setIdleTimeout(30000);
205        client.setConnectTimeout(30000);
206        client.setStopTimeout(30000);
207        client.setRequestBufferSize(1024*1024);
208        client.setResponseBufferSize(1024*1024);
209       
210        return client;
211    }
212}
Note: See TracBrowser for help on using the repository browser.