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

Last change on this file since 1382 was 1382, checked in by pharms, 10 years ago
File size: 7.7 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.httpmonitor.exchange.HttpExchange;
41import de.ugoe.cs.autoquest.httpmonitor.exchange.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    private static final long serialVersionUID = 1L;
61
62    /**
63     * <p>
64     * the HTTP client used internally to send data to the central server
65     * </p>
66     */
67    private HttpClient httpClient;
68   
69    /**
70     * <p>
71     * the host name of the central server
72     * </p>
73     */
74    private String httpMonitorServer;
75   
76    /**
77     * <p>
78     * the port of the central server
79     * </p>
80     */
81    private int httpMonitorPort;
82
83    /**
84     * <p>
85     * a set of requests send to the central server for which the response was not received yet
86     * </p>
87     */
88    private Set<Request> openRequests = new HashSet<Request>();
89   
90    /**
91     * <p>
92     * initializes the exchange handler with the host and port of the central server
93     * </p>
94     *
95     * @param httpMonitorServer the host name of the central server
96     * @param httpMonitorPort   the port of the central server
97     */
98    public HttpMonitorRemoteExchangeHandler(String httpMonitorServer, int httpMonitorPort) {
99        this.httpMonitorServer = httpMonitorServer;
100        this.httpMonitorPort = httpMonitorPort;
101    }
102
103    /* (non-Javadoc)
104     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#init()
105     */
106    @Override
107    public void init() throws IllegalStateException, HttpMonitorException {
108        httpClient = createHttpClient();
109    }
110
111    /* (non-Javadoc)
112     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#start()
113     */
114    @Override
115    public void start() throws IllegalStateException, HttpMonitorException {
116        try {
117            httpClient.start();
118            httpClient.getContentDecoderFactories().clear();
119        }
120        catch (Exception e) {
121            throw new HttpMonitorException("could not start client for HTTP-Monitor", e);
122        }
123    }
124
125    /* (non-Javadoc)
126     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#stop()
127     */
128    @Override
129    public void stop() {
130        if (httpClient != null) {
131            try {
132                httpClient.stop();
133            }
134            catch (Exception e) {
135                Console.traceln(Level.WARNING, "could not stop client for HTTP-Monitor");
136                Console.logException(e);
137            }
138        }
139       
140        httpClient = null;
141    }
142
143    /* (non-Javadoc)
144     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler#handleHttpExchange()
145     */
146    @Override
147    public void handleHttpExchange(HttpExchange httpExchange) {
148        // send the exchange to the server and wait for completion
149        synchronized (openRequests) {
150            Request httpMonitorRequest = httpClient.newRequest(httpMonitorServer, httpMonitorPort);
151            httpMonitorRequest.method(HttpMethod.POST);
152            httpMonitorRequest.version(HttpVersion.HTTP_1_1);
153
154            OutputStreamContentProvider out = new OutputStreamContentProvider();
155            httpMonitorRequest.content(out);
156            httpMonitorRequest.send(this);
157
158            try {
159                JAXBContext jaxbContext =
160                        JAXBContext.newInstance(HttpExchange.class.getPackage().getName());
161                Marshaller marshaller = jaxbContext.createMarshaller();
162
163                OutputStreamWriter writer = new OutputStreamWriter(out.getOutputStream(), "UTF-8");
164                marshaller.marshal(new ObjectFactory().createHttpExchange(httpExchange), writer);
165
166                out.getOutputStream().close();
167            }
168            catch (JAXBException e) {
169                Console.printerrln("could not convert request and response to XML string: " + e);
170                Console.logException(e);
171            }
172            catch (IOException e) {
173                Console.printerrln
174                ("could not close the stream for sending data to the HTML monitor: " + e);
175                Console.logException(e);
176            }
177           
178            openRequests.add(httpMonitorRequest);
179           
180            try {
181                // wait for the request to be removed fromt the list asynchronously
182                while (openRequests.contains(httpMonitorRequest)) {
183                    openRequests.wait();
184                }
185            }
186            catch (InterruptedException e) {
187                // ignore, as this may only happen on system shutdown
188            }
189        }
190    }
191
192    /* (non-Javadoc)
193     * @see org.eclipse.jetty.client.api.Response.CompleteListener#onComplete(Result)
194     */
195    @Override
196    public void onComplete(Result result) {
197        if (result.isFailed()) {
198            Console.traceln
199                (Level.WARNING, "could not log exchange correctly: " + result.getFailure());
200            Console.logException((Exception) result.getFailure());
201        }
202       
203        synchronized (openRequests) {
204            openRequests.remove(result.getRequest());
205            openRequests.notify();
206        }
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.setRequestBufferSize(1024*1024);
224        client.setResponseBufferSize(1024*1024);
225       
226        return client;
227    }
228}
Note: See TracBrowser for help on using the repository browser.