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

Last change on this file since 1565 was 1565, checked in by pharms, 10 years ago
  • prevention of error due to unparseable SOAP message
File size: 7.6 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.InputStream;
22import java.util.Collection;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.logging.Level;
26
27import javax.xml.bind.JAXBContext;
28import javax.xml.bind.JAXBElement;
29import javax.xml.bind.JAXBException;
30import javax.xml.bind.Unmarshaller;
31import javax.xml.soap.MessageFactory;
32import javax.xml.soap.SOAPMessage;
33import javax.xml.transform.stream.StreamSource;
34
35import org.xml.sax.SAXException;
36
37import de.ugoe.cs.autoquest.eventcore.Event;
38import de.ugoe.cs.autoquest.eventcore.IEventType;
39import de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPEventType;
40import de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPTarget;
41import de.ugoe.cs.autoquest.plugin.http.eventcore.SOAPEventType;
42import de.ugoe.cs.autoquest.plugin.http.logdata.Content;
43import de.ugoe.cs.autoquest.plugin.http.logdata.HttpExchange;
44import de.ugoe.cs.autoquest.plugin.http.logdata.Session;
45import de.ugoe.cs.util.console.Console;
46
47/**
48 * <p>
49 * Parser for HTTP Monitor logs. Uses JAXB for parsing and is therefore quite simple. For each
50 * exchange in the log, it creates an appropriate event. It differes between default HTTP events
51 * and SOAP events.
52 * </p>
53 *
54 * @author Patrick Harms
55 */
56public class HTTPLogParser {
57
58    /**
59     * <p>
60     * the event sequences parsed by this parser
61     * </p>
62     */
63    private Collection<List<Event>> sequences = new LinkedList<List<Event>>();
64   
65    /**
66     * <p>
67     * the message factory used for parsing SOAP messages
68     * </p>
69     */
70    private MessageFactory soapMessageFactory;
71
72    /**
73     * <p>
74     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
75     * </p>
76     *
77     * @param filename
78     *            name and path of the log file
79     *
80     * @throws SAXException in the case, the file could not be parsed
81     */
82    public void parseFile(String filename) throws JAXBException {
83        if (filename == null) {
84            throw new IllegalArgumentException("filename must not be null");
85        }
86
87        parseFile(new File(filename));
88    }
89
90    /**
91     * <p>
92     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
93     * </p>
94     *
95     * @param file
96     *            file to be parsed
97     *
98     * @throws SAXException in the case, the file could not be parsed
99     */
100    public void parseFile(File file) throws JAXBException {
101        if (file == null) {
102            throw new IllegalArgumentException("file must not be null");
103        }
104       
105        try {
106                        parseFile(new FileInputStream(file));
107                } catch (FileNotFoundException e) {
108                        Console.printerr("Error parsing file + " + file.getName());
109            Console.logException(e);
110            return;
111                }
112    }
113   
114    /**
115     * <p>
116     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
117     * </p>
118     *
119     * @param stream
120     *            file to be parsed
121     *
122     * @throws SAXException in the case, the file could not be parsed
123     */
124    public void parseFile(InputStream stream) throws JAXBException {
125        if (stream == null) {
126            throw new IllegalArgumentException("stream must not be null");
127        }
128       
129        JAXBContext jc = JAXBContext.newInstance(Session.class.getPackage().getName());
130       
131        Unmarshaller unmarshaller = jc.createUnmarshaller();
132        StreamSource source = new StreamSource(stream);
133       
134        @SuppressWarnings("unchecked")
135        JAXBElement<Session> sessionObj = (JAXBElement<Session>) unmarshaller.unmarshal(source);
136       
137        Session session = sessionObj.getValue();
138
139        if ((session.getHttpExchange() != null) && (session.getHttpExchange().size() > 0)) {
140            List<Event> sequence = new LinkedList<Event>();
141            for (HttpExchange exchange : session.getHttpExchange()) {
142                sequence.add(new Event(createEvent(exchange),
143                                       new HTTPTarget(exchange.getReceiver())));
144            }
145            sequences.add(sequence);
146        }
147       
148    }
149
150    /**
151     * <p>
152     * instantiates the appropriate event type. If it encounters a SOAP exchange, a SOAP event type
153     * is instantiated. Otherwise a normal HTTP event type is created.
154     * </p>
155     *
156     * @param exchange the exchange for which an event type is to be created
157     *
158     * @return as described
159     */
160    private IEventType createEvent(HttpExchange exchange) {
161        Content requestContent =
162            exchange.getRequest() != null ? exchange.getRequest().getContent() : null;
163       
164        SOAPMessage soapRequest = getSOAPMessage(requestContent);
165       
166        Content responseContent =
167            exchange.getResponse() != null ? exchange.getResponse().getContent() : null;
168           
169        SOAPMessage soapResponse = getSOAPMessage(responseContent);
170       
171        if (soapRequest != null) {
172            return new SOAPEventType(exchange, soapRequest, soapResponse);
173        }
174        else {
175            return new HTTPEventType(exchange);
176        }
177    }
178
179    /**
180     * <p>
181     * convenience method to convert the content of an HTTP request or response into a SOAP message
182     * </p>
183     *
184     * @param content the content to be converted into a SOAP message
185     *
186     * @return the SOAP message contained in the content or null if either the content is null or
187     *         the content does not contain a SOAP message
188     */
189    private SOAPMessage getSOAPMessage(Content content) {
190        if ((content != null) && (content.getData() != null)) {
191            try {
192                if (soapMessageFactory == null) {
193                    soapMessageFactory = MessageFactory.newInstance();
194                }
195           
196                String encoding = content.getEncoding();
197                if (encoding == null) {
198                    encoding = "UTF-8";
199                }
200               
201                InputStream in = new ByteArrayInputStream(content.getData().getBytes(encoding));
202                SOAPMessage message = soapMessageFactory.createMessage(null, in);
203               
204                // try to access something to see, if everything worked fine.
205                message.getSOAPHeader();
206                message.getSOAPBody();
207               
208                return message;
209            }
210            catch (Exception e) {
211                if (content.getData().toLowerCase().indexOf("envelope") > 0) {
212                    Console.traceln(Level.WARNING, "HTTP message seems to be a SOAP message but " +
213                                    "it could not be parsed as such: " + e);
214                    //Console.logException(e);
215                }
216            }
217        }
218       
219        return null;
220    }
221
222    /**
223     * <p>
224     * returns the sequences parsed by this parser
225     * </p>
226     *
227     * @return as described
228     */
229    public Collection<List<Event>> getSequences() {
230        return sequences;
231    }
232}
Note: See TracBrowser for help on using the repository browser.