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

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