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

Last change on this file since 1614 was 1614, checked in by pharms, 10 years ago
  • bugfix and test for correct query handling
File size: 7.8 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.io.IOException;
18import java.io.OutputStreamWriter;
19import java.util.HashSet;
20import java.util.Set;
21import java.util.logging.Level;
22
23import javax.xml.bind.JAXBContext;
24import javax.xml.bind.JAXBException;
25import javax.xml.bind.Marshaller;
26
27import org.eclipse.jetty.client.HttpClient;
28import org.eclipse.jetty.client.api.Request;
29import org.eclipse.jetty.client.api.Response.CompleteListener;
30import org.eclipse.jetty.client.api.Result;
31import org.eclipse.jetty.client.util.OutputStreamContentProvider;
32import org.eclipse.jetty.http.HttpMethod;
33import org.eclipse.jetty.http.HttpVersion;
34import org.eclipse.jetty.util.thread.QueuedThreadPool;
35
36import de.ugoe.cs.autoquest.httpmonitor.HttpMonitor;
37import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
38import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
39import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler;
40import de.ugoe.cs.autoquest.plugin.http.logdata.HttpExchange;
41import de.ugoe.cs.autoquest.plugin.http.logdata.ObjectFactory;
42import de.ugoe.cs.util.console.Console;
43
44/**
45 * <p>
46 * If the exchanges recorded by the proxy are to be transmitted to a central {@link HttpMonitor},
47 * this exchanges handler is used. It is called by the exchange listener on completion of a proxied
48 * request/response. It then creates an HTTP request to the central monitor and sends it there.
49 * It is initialized with the name of the server and the port on which the central monitor runs.
50 * If the exchanges can not be forwarded to the central server, they are discarded.
51 * </p>
52 *
53 * @author Patrick Harms
54 */
55public class HttpMonitorRemoteExchangeHandler
56    implements CompleteListener, HttpMonitorExchangeHandler, HttpMonitorComponent
57{
58
59    /**
60     * <p>
61     * the HTTP client used internally to send data to the central server
62     * </p>
63     */
64    private HttpClient httpClient;
65   
66    /**
67     * <p>
68     * the host name of the central server
69     * </p>
70     */
71    private String httpMonitorServer;
72   
73    /**
74     * <p>
75     * the port of the central server
76     * </p>
77     */
78    private int httpMonitorPort;
79
80    /**
81     * <p>
82     * a set of requests send to the central server for which the response was not received yet
83     * </p>
84     */
85    private Set<Request> openRequests = new HashSet<Request>();
86   
87    /**
88     * <p>
89     * initializes the exchange handler with the host and port of the central server
90     * </p>
91     *
92     * @param httpMonitorServer the host name of the central server
93     * @param httpMonitorPort   the port of the central server
94     */
95    public HttpMonitorRemoteExchangeHandler(String httpMonitorServer, int httpMonitorPort) {
96        this.httpMonitorServer = httpMonitorServer;
97        this.httpMonitorPort = httpMonitorPort;
98    }
99
100    /* (non-Javadoc)
101     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#init()
102     */
103    @Override
104    public void init() throws IllegalStateException, HttpMonitorException {
105        httpClient = createHttpClient();
106    }
107
108    /* (non-Javadoc)
109     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#start()
110     */
111    @Override
112    public void start() throws IllegalStateException, HttpMonitorException {
113        try {
114            httpClient.start();
115            httpClient.getContentDecoderFactories().clear();
116        }
117        catch (Exception e) {
118            throw new HttpMonitorException("could not start client for HTTP-Monitor", e);
119        }
120    }
121
122    /* (non-Javadoc)
123     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#stop()
124     */
125    @Override
126    public void stop() {
127        if (httpClient != null) {
128            try {
129                httpClient.stop();
130            }
131            catch (Exception e) {
132                Console.traceln(Level.WARNING, "could not stop client for HTTP-Monitor");
133                Console.logException(e);
134            }
135        }
136       
137        httpClient = null;
138    }
139
140    /* (non-Javadoc)
141     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler#handleHttpExchange()
142     */
143    @Override
144    public synchronized void handleHttpExchange(HttpExchange httpExchange) {
145        // send the exchange to the server and wait for completion
146        Request httpMonitorRequest = httpClient.newRequest(httpMonitorServer, httpMonitorPort);
147        httpMonitorRequest.method(HttpMethod.POST);
148        httpMonitorRequest.version(HttpVersion.HTTP_1_1);
149
150        OutputStreamContentProvider out = new OutputStreamContentProvider();
151        httpMonitorRequest.content(out);
152       
153        openRequests.add(httpMonitorRequest);
154        httpMonitorRequest.send(this);
155
156        try {
157            JAXBContext jaxbContext =
158                JAXBContext.newInstance(HttpExchange.class.getPackage().getName());
159            Marshaller marshaller = jaxbContext.createMarshaller();
160
161            OutputStreamWriter writer = new OutputStreamWriter(out.getOutputStream(), "UTF-8");
162            marshaller.marshal(new ObjectFactory().createHttpExchange(httpExchange), writer);
163
164            out.getOutputStream().close();
165        }
166        catch (JAXBException e) {
167            Console.printerrln("could not convert request and response to XML string: " + e);
168            Console.logException(e);
169        }
170        catch (IOException e) {
171            Console.printerrln
172                ("could not close the stream for sending data to the HTML monitor: " + e);
173            Console.logException(e);
174        }
175
176        try {
177            // wait for the request to be removed from the list asynchronously
178            int count = 30;
179            while (openRequests.contains(httpMonitorRequest)) {
180                this.wait(1000);
181               
182                if (--count == 0) {
183                    // after 30 seconds, cancel the sending of the loggin request
184                    openRequests.remove(httpMonitorRequest);
185                    break;
186                }
187            }
188        }
189        catch (InterruptedException e) {
190            // ignore, as this may only happen on system shutdown
191        }
192    }
193
194    /* (non-Javadoc)
195     * @see org.eclipse.jetty.client.api.Response.CompleteListener#onComplete(Result)
196     */
197    @Override
198    public synchronized void onComplete(Result result) {
199        if (result.isFailed()) {
200            Console.traceln
201                (Level.WARNING, "could not log exchange correctly: " + result.getFailure());
202            Console.logException((Exception) result.getFailure());
203        }
204       
205        openRequests.remove(result.getRequest());
206        this.notify();
207    }
208
209    /**
210     * <p>
211     * convenience method to create an initialize the utilized HTTP client
212     * </p>
213     */
214    private HttpClient createHttpClient() {
215        HttpClient client = new HttpClient();
216       
217        QueuedThreadPool executor = new QueuedThreadPool(10);
218        executor.setName("HttpMonitorClients");
219        client.setExecutor(executor);
220
221        client.setMaxConnectionsPerDestination(10000);
222        client.setIdleTimeout(30000);
223        client.setConnectTimeout(30000);
224        client.setStopTimeout(30000);
225        client.setRequestBufferSize(1024*1024);
226        client.setResponseBufferSize(1024*1024);
227       
228        return client;
229    }
230}
Note: See TracBrowser for help on using the repository browser.