source: trunk/autoquest-plugin-http/src/main/java/de/ugoe/cs/autoquest/plugin/http/HTTPLogParser.java @ 2218

Last change on this file since 2218 was 2218, checked in by pharms, 7 years ago
  • java doc issues removal
File size: 10.0 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.plugin.http;
16
17import java.io.ByteArrayInputStream;
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.FileNotFoundException;
21import java.io.IOException;
22import java.io.InputStream;
23import java.util.Collection;
24import java.util.LinkedList;
25import java.util.List;
26import java.util.Properties;
27import java.util.logging.Level;
28import java.util.logging.Logger;
29
30import javax.xml.bind.JAXBContext;
31import javax.xml.bind.JAXBElement;
32import javax.xml.bind.JAXBException;
33import javax.xml.bind.Unmarshaller;
34import javax.xml.soap.MessageFactory;
35import javax.xml.soap.SOAPMessage;
36import javax.xml.transform.stream.StreamSource;
37
38import de.ugoe.cs.autoquest.eventcore.Event;
39import de.ugoe.cs.autoquest.eventcore.IEventType;
40import de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPEventType;
41import de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPTarget;
42import de.ugoe.cs.autoquest.plugin.http.eventcore.SOAPEventType;
43import de.ugoe.cs.autoquest.plugin.http.logdata.Content;
44import de.ugoe.cs.autoquest.plugin.http.logdata.HttpExchange;
45import de.ugoe.cs.autoquest.plugin.http.logdata.Session;
46import de.ugoe.cs.util.console.Console;
47
48/**
49 * <p>
50 * Parser for HTTP Monitor logs. Uses JAXB for parsing and is therefore quite simple. For each
51 * exchange in the log, it creates an appropriate event. It differes between default HTTP events
52 * and SOAP events.
53 * </p>
54 *
55 * @author Patrick Harms
56 */
57public class HTTPLogParser {
58
59    /**
60     * <p>
61     * the event sequences parsed by this parser
62     * </p>
63     */
64    private Collection<List<Event>> sequences = new LinkedList<List<Event>>();
65   
66    /**
67     * <p>
68     * the message factory used for parsing SOAP messages
69     * </p>
70     */
71    private MessageFactory soapMessageFactory;
72   
73    /**
74     * <p>
75     * properties used to map the path of a service to its logical name
76     * </p>
77     */
78    private Properties urlNameMap = null;
79   
80    /**
81     * <p>
82     * Constructor. Creates a new HTTPLogParser without a urlNameMap.
83     * </p>
84     */
85    public HTTPLogParser() {
86        Logger.getLogger("com.sun.xml.internal.messaging.saaj").setLevel(Level.OFF);
87    }
88   
89    /**
90     * <p>
91     * Constructor. Creates a new HTTPLogParser with a urlNameMap
92     * </p>
93     *
94     * @param urlNameMapFile properties file with the path to logical name map
95     * @throws IOException thrown if there is an error load in the service name map
96     */
97    public HTTPLogParser(File urlNameMapFile) throws IOException {
98        this(new FileInputStream(urlNameMapFile));
99    }
100   
101    /**
102     * <p>
103     * Constructor. Creates a new HTTPLogParser with a urlNameMap
104     * </p>
105     *
106     * @param urlNameMapStream properties file with the path to logical name map
107     * @throws IOException thrown if there is an error load in the service name map
108     */
109    public HTTPLogParser(InputStream urlNameMapStream) throws IOException {
110        this();
111        urlNameMap = new Properties();
112        urlNameMap.load(urlNameMapStream);
113    }
114   
115    /**
116     * <p>
117     * Constructor. Creates a new HTTPLogParser with a urlNameMap.
118     * </p>
119     *
120     * @param urlNameMapFile properties that include the logical name map
121     */
122    public HTTPLogParser(Properties urlNameMapFile) {
123        this();
124        urlNameMap = urlNameMapFile;
125    }
126
127    /**
128     * <p>
129     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
130     * </p>
131     *
132     * @param filename
133     *            name and path of the log file
134     *
135     * @throws JAXBException in the case, the file could not be parsed
136     */
137    public void parseFile(String filename) throws JAXBException {
138        if (filename == null) {
139            throw new IllegalArgumentException("filename must not be null");
140        }
141
142        parseFile(new File(filename));
143    }
144
145    /**
146     * <p>
147     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
148     * </p>
149     *
150     * @param file
151     *            file to be parsed
152     *
153     * @throws JAXBException in the case, the file could not be parsed
154     */
155    public void parseFile(File file) throws JAXBException {
156        if (file == null) {
157            throw new IllegalArgumentException("file must not be null");
158        }
159       
160        try {
161            parseFile(new FileInputStream(file));
162        }
163        catch (FileNotFoundException e) {
164            Console.printerr("Error parsing file + " + file.getName());
165            Console.logException(e);
166            return;
167        }
168    }
169   
170    /**
171     * <p>
172     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
173     * </p>
174     *
175     * @param stream
176     *            file to be parsed
177     *
178     * @throws JAXBException in the case, the file could not be parsed
179     */
180    public void parseFile(InputStream stream) throws JAXBException {
181        if (stream == null) {
182            throw new IllegalArgumentException("stream must not be null");
183        }
184       
185        JAXBContext jc = JAXBContext.newInstance(Session.class.getPackage().getName());
186       
187        Unmarshaller unmarshaller = jc.createUnmarshaller();
188        StreamSource source = new StreamSource(stream);
189       
190        @SuppressWarnings("unchecked")
191        JAXBElement<Session> sessionObj = (JAXBElement<Session>) unmarshaller.unmarshal(source);
192       
193        Session session = sessionObj.getValue();
194
195        long orderingId = 0;
196        if ((session.getHttpExchange() != null) && (session.getHttpExchange().size() > 0)) {
197            List<Event> sequence = new LinkedList<Event>();
198            for (HttpExchange exchange : session.getHttpExchange()) {
199               
200                // check, if the exchange is an old one and does not contain ordering ids yet.
201                // If not, then add them.
202                if (exchange.getRequest().getOrderingId() == null) {
203                    exchange.getRequest().setOrderingId(orderingId++);
204                }
205                else {
206                    orderingId = exchange.getRequest().getOrderingId();
207                }
208               
209                if (exchange.getResponse().getOrderingId() == null) {
210                    exchange.getResponse().setOrderingId(orderingId++);
211                }
212                else {
213                    orderingId = exchange.getResponse().getOrderingId();
214                }
215               
216                // now handle the exchange
217                sequence.add(new Event(createEvent(exchange),
218                                       new HTTPTarget(exchange.getReceiver())));
219            }
220            sequences.add(sequence);
221        }
222       
223    }
224
225    /**
226     * <p>
227     * instantiates the appropriate event type. If it encounters a SOAP exchange, a SOAP event type
228     * is instantiated. Otherwise a normal HTTP event type is created.
229     * </p>
230     *
231     * @param exchange the exchange for which an event type is to be created
232     *
233     * @return as described
234     */
235    private IEventType createEvent(HttpExchange exchange) {
236        Content requestContent =
237            exchange.getRequest() != null ? exchange.getRequest().getContent() : null;
238       
239        SOAPMessage soapRequest = getSOAPMessage(requestContent);
240       
241        Content responseContent =
242            exchange.getResponse() != null ? exchange.getResponse().getContent() : null;
243           
244        SOAPMessage soapResponse = getSOAPMessage(responseContent);
245       
246        if (soapRequest != null) {
247            return new SOAPEventType(exchange, soapRequest, soapResponse, urlNameMap);
248        }
249        else {
250            return new HTTPEventType(exchange);
251        }
252    }
253
254    /**
255     * <p>
256     * convenience method to convert the content of an HTTP request or response into a SOAP message
257     * </p>
258     *
259     * @param content the content to be converted into a SOAP message
260     *
261     * @return the SOAP message contained in the content or null if either the content is null or
262     *         the content does not contain a SOAP message
263     */
264    private SOAPMessage getSOAPMessage(Content content) {
265        if ((content != null) && (content.getData() != null)) {
266            try {
267                if (soapMessageFactory == null) {
268                    soapMessageFactory = MessageFactory.newInstance();
269                }
270           
271                String encoding = content.getEncoding();
272                if (encoding == null) {
273                    encoding = "UTF-8";
274                }
275               
276                InputStream in = new ByteArrayInputStream(content.getData().getBytes(encoding));
277                SOAPMessage message = soapMessageFactory.createMessage(null, in);
278               
279                // try to access something to see, if everything worked fine.
280                message.getSOAPHeader();
281                message.getSOAPBody();
282               
283                return message;
284            }
285            catch (Exception e) {
286                if (content.getData().toLowerCase().indexOf("envelope") > 0) {
287                    Console.traceln(Level.WARNING, "HTTP message seems to be a SOAP message but " +
288                                    "it could not be parsed as such: " + e);
289                    //Console.logException(e);
290                }
291            }
292        }
293       
294        return null;
295    }
296
297    /**
298     * <p>
299     * returns the sequences parsed by this parser
300     * </p>
301     *
302     * @return as described
303     */
304    public Collection<List<Event>> getSequences() {
305        return sequences;
306    }
307}
Note: See TracBrowser for help on using the repository browser.