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

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