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

Last change on this file since 1622 was 1622, checked in by sherbold, 10 years ago
  • added possibility to map paths to logical service names to HTTPLogParser
  • extended SOAPEventType with serviceName attribute
File size: 8.5 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
97     * @throws 
98     */
99    public HTTPLogParser(File urlNameMapFile) throws IOException {
100        super();
101        urlNameMap = new Properties();
102        urlNameMap.load(new FileInputStream(urlNameMapFile));
103    }
104
105    /**
106     * <p>
107     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
108     * </p>
109     *
110     * @param filename
111     *            name and path of the log file
112     *
113     * @throws SAXException in the case, the file could not be parsed
114     */
115    public void parseFile(String filename) throws JAXBException {
116        if (filename == null) {
117            throw new IllegalArgumentException("filename must not be null");
118        }
119
120        parseFile(new File(filename));
121    }
122
123    /**
124     * <p>
125     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
126     * </p>
127     *
128     * @param file
129     *            file to be parsed
130     *
131     * @throws SAXException in the case, the file could not be parsed
132     */
133    public void parseFile(File file) throws JAXBException {
134        if (file == null) {
135            throw new IllegalArgumentException("file must not be null");
136        }
137       
138        try {
139            parseFile(new FileInputStream(file));
140        }
141        catch (FileNotFoundException e) {
142            Console.printerr("Error parsing file + " + file.getName());
143            Console.logException(e);
144            return;
145        }
146    }
147   
148    /**
149     * <p>
150     * Parses a log file written by the HTTPMonitor and creates a collection of event sequences.
151     * </p>
152     *
153     * @param stream
154     *            file to be parsed
155     *
156     * @throws SAXException in the case, the file could not be parsed
157     */
158    public void parseFile(InputStream stream) throws JAXBException {
159        if (stream == null) {
160            throw new IllegalArgumentException("stream must not be null");
161        }
162       
163        JAXBContext jc = JAXBContext.newInstance(Session.class.getPackage().getName());
164       
165        Unmarshaller unmarshaller = jc.createUnmarshaller();
166        StreamSource source = new StreamSource(stream);
167       
168        @SuppressWarnings("unchecked")
169        JAXBElement<Session> sessionObj = (JAXBElement<Session>) unmarshaller.unmarshal(source);
170       
171        Session session = sessionObj.getValue();
172
173        if ((session.getHttpExchange() != null) && (session.getHttpExchange().size() > 0)) {
174            List<Event> sequence = new LinkedList<Event>();
175            for (HttpExchange exchange : session.getHttpExchange()) {
176                sequence.add(new Event(createEvent(exchange),
177                                       new HTTPTarget(exchange.getReceiver())));
178            }
179            sequences.add(sequence);
180        }
181       
182    }
183
184    /**
185     * <p>
186     * instantiates the appropriate event type. If it encounters a SOAP exchange, a SOAP event type
187     * is instantiated. Otherwise a normal HTTP event type is created.
188     * </p>
189     *
190     * @param exchange the exchange for which an event type is to be created
191     *
192     * @return as described
193     */
194    private IEventType createEvent(HttpExchange exchange) {
195        Content requestContent =
196            exchange.getRequest() != null ? exchange.getRequest().getContent() : null;
197       
198        SOAPMessage soapRequest = getSOAPMessage(requestContent);
199       
200        Content responseContent =
201            exchange.getResponse() != null ? exchange.getResponse().getContent() : null;
202           
203        SOAPMessage soapResponse = getSOAPMessage(responseContent);
204       
205        if (soapRequest != null) {
206            return new SOAPEventType(exchange, soapRequest, soapResponse, urlNameMap);
207        }
208        else {
209            return new HTTPEventType(exchange);
210        }
211    }
212
213    /**
214     * <p>
215     * convenience method to convert the content of an HTTP request or response into a SOAP message
216     * </p>
217     *
218     * @param content the content to be converted into a SOAP message
219     *
220     * @return the SOAP message contained in the content or null if either the content is null or
221     *         the content does not contain a SOAP message
222     */
223    private SOAPMessage getSOAPMessage(Content content) {
224        if ((content != null) && (content.getData() != null)) {
225            try {
226                if (soapMessageFactory == null) {
227                    soapMessageFactory = MessageFactory.newInstance();
228                }
229           
230                String encoding = content.getEncoding();
231                if (encoding == null) {
232                    encoding = "UTF-8";
233                }
234               
235                InputStream in = new ByteArrayInputStream(content.getData().getBytes(encoding));
236                SOAPMessage message = soapMessageFactory.createMessage(null, in);
237               
238                // try to access something to see, if everything worked fine.
239                message.getSOAPHeader();
240                message.getSOAPBody();
241               
242                return message;
243            }
244            catch (Exception e) {
245                if (content.getData().toLowerCase().indexOf("envelope") > 0) {
246                    Console.traceln(Level.WARNING, "HTTP message seems to be a SOAP message but " +
247                                    "it could not be parsed as such: " + e);
248                    //Console.logException(e);
249                }
250            }
251        }
252       
253        return null;
254    }
255
256    /**
257     * <p>
258     * returns the sequences parsed by this parser
259     * </p>
260     *
261     * @return as described
262     */
263    public Collection<List<Event>> getSequences() {
264        return sequences;
265    }
266}
Note: See TracBrowser for help on using the repository browser.