// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.plugin.http.eventcore; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.collections4.set.ListOrderedSet; import org.w3c.dom.Element; import org.xml.sax.SAXException; import de.ugoe.cs.autoquest.eventcore.IEventType; import de.ugoe.cs.autoquest.plugin.http.HTTPUtils; import de.ugoe.cs.autoquest.plugin.http.SOAPUtils; /** *

* A simplified SOAP event type that only contains the name of the called method and the name of the * service. *

* * @author Steffen Herbold */ public class SimpleSOAPEventType implements IEventType { /** */ private static final long serialVersionUID = 1L; /** * see {@link RequestBodyMode} */ private static RequestBodyMode requestBodyMode = RequestBodyMode.LOCALEVENT; /** *

* the SOAP method called in this request *

*/ private final String calledMethod; /** *

* the name of the service; this is either the path or, if a path map is available *

*/ private final String serviceName; /** *

* the name of the client; this is either the host/ip and port of the sender or, if a path map * is available, a human readable name that may be based also on the receiver *

*/ private final String clientName; /** *

* the body of the SOAP request; storage as serialized XML string to allow object serialization *

*/ private final String soapRequestBody; /** *

* Constructor. Creates a new SimpleSOAPEventType. *

* */ public SimpleSOAPEventType(String calledMethod, String serviceName, String clientName, Element soapRequestBody) { if (calledMethod == null) { throw new IllegalArgumentException("called method must not be null"); } if (serviceName == null) { throw new IllegalArgumentException("serviceName must not be null"); } if (clientName == null) { throw new IllegalArgumentException("clientName must not be null"); } this.calledMethod = calledMethod; this.serviceName = serviceName; this.clientName = clientName; this.soapRequestBody = SOAPUtils.getSerialization(soapRequestBody); EqualSOAPDataMap.INSTANCE.add(this, this.soapRequestBody); } /** *

* the SOAP method called in this request *

* * @return the SOAP method called in this request */ public String getCalledMethod() { return calledMethod; } /** *

* the name of the service called in this request *

* * @return the name of the service called in this request */ public String getServiceName() { return serviceName; } /** *

* the name of the client calling in this request *

* * @return the name of the client calling in this request */ public String getClientName() { return clientName; } /** *

* returns the body of the SOAP request; how the body is determined is defined by the {@link RequestBodyMode}. *

* * @return body of the SOAP request */ public Element getSoapRequestBody() { String requestBody; switch (requestBodyMode) { case LOCALEVENT: requestBody = soapRequestBody; break; case RANDOM: requestBody = EqualSOAPDataMap.INSTANCE.getRandom(this); break; default: throw new RuntimeException("undefined RequestBodyMode"); } if( requestBody==null ) { System.err.println("foobar" + this); System.err.println(EqualSOAPDataMap.INSTANCE.getAll(this)); } try { return DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new ByteArrayInputStream(requestBody.getBytes())).getDocumentElement(); } catch (SAXException | IOException | ParserConfigurationException e) { return null; } } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.eventcore.IEventType#getName() */ @Override public String getName() { return "(" + serviceName + ", " + calledMethod + ")"; } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPEventType#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof SimpleSOAPEventType) { return HTTPUtils.equals(calledMethod, ((SimpleSOAPEventType) obj).calledMethod) && HTTPUtils.equals(serviceName, ((SimpleSOAPEventType) obj).serviceName) && HTTPUtils.equals(clientName, ((SimpleSOAPEventType) obj).clientName); } else { return false; } } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.plugin.http.eventcore.HTTPEventType#hashCode() */ @Override public int hashCode() { int hashCode = calledMethod.hashCode() + serviceName.hashCode() + clientName.hashCode(); return hashCode; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return "SimpleSOAPEventType(" + serviceName + ", " + calledMethod + ")"; } /** *

* returns the current {@link RequestBodyMode} *

* * @return the requestBodyMode */ public static RequestBodyMode getRequestBodyMode() { return requestBodyMode; } /** *

* sets the {@link RequestBodyMode} *

* * @param new requestBodyMode */ public static void setRequestBodyMode(RequestBodyMode requestBodyMode) { SimpleSOAPEventType.requestBodyMode = requestBodyMode; } /** *

* Determines how getSoapRequestBody works. *

*

* * @author Steffen Herbold */ public static enum RequestBodyMode {LOCALEVENT, RANDOM}; /** *

* Handles all request bodies of equal SOAP events. Can be used to view either all request bodies sent to an operation or to randomly draw one of the bodies. *

* * @author Steffen Herbold */ public static class EqualSOAPDataMap { /** * Singleton. Handle to only instance of this class */ public final static EqualSOAPDataMap INSTANCE = new EqualSOAPDataMap(); /** * Map with all soapRequestBodies for all equal {@link SimpleSOAPEventType}s */ private final Map> soapRequestBodies = new HashMap<>(); /** * random number generator for picking a random request body */ private final Random random = new Random(1); // TODO static seed for testing private EqualSOAPDataMap() { // private constructor to avoid initialization } /** *

* Adds a new body to the map. *

* * @param simpleSOAPEventType */ public void add(SimpleSOAPEventType simpleSOAPEventType, String soapRequestBody) { if( soapRequestBody!=null ) { ListOrderedSet requestBodySet = soapRequestBodies.get(simpleSOAPEventType); if( requestBodySet==null ) { requestBodySet = new ListOrderedSet<>(); soapRequestBodies.put(simpleSOAPEventType, requestBodySet); } requestBodySet.add(soapRequestBody); } } /** *

* Retrieves all bodies associated with the simpleSoapEventType; null if not found *

* * @param simpleSoapEventType * @return */ public Set getAll(SimpleSOAPEventType simpleSoapEventType) { return Collections.unmodifiableSet(soapRequestBodies.get(simpleSoapEventType)); } /** *

* Randomly draws one of the SOAP event type bodies associated with the event *

* * @param simpleSOAPEventType * @return */ public String getRandom(SimpleSOAPEventType simpleSOAPEventType) { ListOrderedSet requestBodySet = soapRequestBodies.get(simpleSOAPEventType); if( requestBodySet==null || requestBodySet.isEmpty() ) { throw new RuntimeException("no request body known for SimpleSOAPEventType: " + simpleSOAPEventType); } return requestBodySet.get(random.nextInt(requestBodySet.size())); } } }