// 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; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.plugin.http.eventcore.EqualSOAPDataMap; import de.ugoe.cs.autoquest.plugin.http.eventcore.SOAPEventType; import de.ugoe.cs.autoquest.plugin.http.eventcore.SimpleSOAPEventType; /** *

* Utilities for working with SOAP events. Their main task is to simply working with * {@link SimpleSOAPEventType} and {@link SOAPEventType}. *

* * @author Steffen Herbold */ public class SOAPUtils { /** *

* Replaces events with a {@link SOAPEventType} with new events of {@link SimpleSOAPEventType} * and no target. *

* * @param sequences * sequences where the events are replaced * @param keepOnlySOAPEvents * if true, all events that are not of SOAPEventType or SimpleSOAPEventType are * removed * @return sequences with {@link SimpleSOAPEventType}s instead of {@link SOAPEventType}s */ public static Collection> convertToSimpleSOAPEvent(Collection> sequences, boolean keepOnlySOAPEvents) { Collection> newSequences = new LinkedList<>(); EqualSOAPDataMap equalSOAPDataMap = new EqualSOAPDataMap(); for( List sequence : sequences ) { List newSequence = null; if (sequence != null) { newSequence = new LinkedList<>(); for (Event event : sequence) { if (event.getType() instanceof SOAPEventType) { SOAPEventType eventType = (SOAPEventType) event.getType(); newSequence.add(new Event(new SimpleSOAPEventType(eventType.getCalledMethod(), eventType.getServiceName(), eventType.getClientName(), eventType .getSoapRequestBody(), equalSOAPDataMap))); } else { if (!keepOnlySOAPEvents || event.getType() instanceof SimpleSOAPEventType) { newSequence.add(event); } } } } newSequences.add(newSequence); } return newSequences; } /** *

* Removes all non SOAP events from a sequence. Warning: this change is performed in-place! *

* * @param sequence * sequence where the events are replaced */ public static void removeNonSOAPEvents(List sequence) { for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) { Event event = eventIter.next(); if (!(event.getType() instanceof SOAPEventType)) { eventIter.remove(); } } } /** *

* Helper function to get the name of a service from a SOAP event. *

* * @param event * event for which the service name is retrieved * @return service name */ public static String getServiceNameFromEvent(Event event) { if (event.getType() instanceof SOAPEventType) { return ((SOAPEventType) event.getType()).getServiceName(); } else if (event.getType() instanceof SimpleSOAPEventType) { return ((SimpleSOAPEventType) event.getType()).getServiceName(); } else { throw new RuntimeException( "Wrong event type. Only SOAPEventType and SimpleSOAPEventType supported but was: " + event.getType().getClass().getName()); } } /** * *

* Helper function to get the called method from a SOAP event *

* * @param event * event for which the called method is retrieved * @return called method */ public static String getCalledMethodFromEvent(Event event) { if (event.getType() instanceof SOAPEventType) { return ((SOAPEventType) event.getType()).getCalledMethod(); } else if (event.getType() instanceof SimpleSOAPEventType) { return ((SimpleSOAPEventType) event.getType()).getCalledMethod(); } else { throw new RuntimeException( "Wrong event type. Only SOAPEventType and SimpleSOAPEventType supported but was: " + event.getType().getClass().getName()); } } /** *

* Helper function to get the name of a client from a SOAP event. *

* * @param event * event for which the client name is retrieved * @return service name */ public static String getClientNameFromEvent(Event event) { if (event.getType() instanceof SOAPEventType) { return ((SOAPEventType) event.getType()).getClientName(); } else if (event.getType() instanceof SimpleSOAPEventType) { return ((SimpleSOAPEventType) event.getType()).getClientName(); } else { throw new RuntimeException( "Wrong event type. Only SOAPEventType and SimpleSOAPEventType supported but was: " + event.getType().getClass().getName()); } } /** *

* Helper function to get the body of a SOAP request. *

* * @param event * event for which the SOAP request body is retrieved * @return body of the SOAP event */ public static Element getSoapRequestBodyFromEvent(Event event) { return getSoapRequestBodyFromEvent(event, false); } /** *

* Helper function to get the body of a SOAP request. *

* * @param event * event for which the SOAP request body is retrieved * @param useRandomRequestBodies * defines is random request bodies are used or the body of the associated event * @return body of the SOAP event */ public static Element getSoapRequestBodyFromEvent(Event event, boolean useRandomRequestBodies) { Element requestBody = null; if (event.getType() instanceof SOAPEventType) { requestBody = ((SOAPEventType) event.getType()).getSoapRequestBody(); } else if (event.getType() instanceof SimpleSOAPEventType) { if( useRandomRequestBodies ) { requestBody = ((SimpleSOAPEventType) event.getType()).getRandomSoapRequestBody(); } else { requestBody = ((SimpleSOAPEventType) event.getType()).getSoapRequestBody(); } } return requestBody; } /** *

* returns the XML serialization of a DOM node; located here because it is used for SOAP request * bodies *

* * @param node * DOM node that is serialized * @return XML serialization as String; null if node is null */ public static String getSerialization(Node node) { if (node == null) { return null; } try { StringWriter writer = new StringWriter(); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(new DOMSource(node), new StreamResult(writer)); return writer.toString(); } catch (TransformerFactoryConfigurationError | TransformerException e) { throw new IllegalArgumentException( "could not create serialization for SOAP request body.", e); } } /** *

* Fetches all {@link Element}s that are direct children of the parent node, whose name matches * the given name. *

* * @param typeNameRaw * name of elements that are looked for * @param parentNode * DOM node in which the elements are searched for * @return found {@link Element}s */ public static List getMatchingChildNode(String typeNameRaw, Element parentNode) { List matchingNodes = new ArrayList<>(); Node parameterNode = null; if (parentNode != null) { NodeList parameterNodes = parentNode.getChildNodes(); String[] typeNameSplit = typeNameRaw.split(":"); String typeName = typeNameSplit[typeNameSplit.length - 1]; for (int i = 0; i < parameterNodes.getLength(); i++) { parameterNode = parameterNodes.item(i); if (parameterNode.getNodeType() == Node.ELEMENT_NODE) { String[] parameterNodeSplit = parameterNode.getNodeName().split(":"); String parameterNodeName = parameterNodeSplit[parameterNodeSplit.length - 1]; if (typeName.equals(parameterNodeName)) { matchingNodes.add((Element) parameterNode); } } } } return matchingNodes; } /** *

* Returns the values found in a currentNode for a defined valueName. To this aim, this methods * first determines if there is an attribute with the name "valueName". If this is the case, the * value of this attribute is returned. Otherwise, the methods looks for {@link Element}s that * are direct children of the provided DOM node with the given name and returns the text content * of those nodes. *

*

* In case no values can be found, an empty list is returned * * @param valueName * name of the value that is retrieved * @param node * node for which the value is retrieved * @return list of the found values. */ public static List getValuesFromElement(String valueName, Element node) { List attributeValues = new LinkedList<>(); if (node != null) { // first check attributes of the node Attr attribute = node.getAttributeNode(valueName); if (attribute != null) { attributeValues.add(attribute.getValue()); } else { // now check elements List elements = getMatchingChildNode(valueName, node); for (Element element : elements) { attributeValues.add(element.getTextContent()); } } } return attributeValues; } /** *

* Allows the removal of pre- and suffixes from SOAP operation names in {@link SimpleSOAPEventType}. *

* * @param sequences sequences where the operation names are normalized */ public static Collection> normalizeOperationNames(Collection> sequences, String prefixToRemove, String suffixToRemove) { Collection> normalizedSequences = new LinkedList<>(); for(List sequence : sequences ) { List normalizedSequence = new LinkedList<>(); for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) { Event event = eventIter.next(); if ((event.getType() instanceof SimpleSOAPEventType)) { SimpleSOAPEventType eventType = (SimpleSOAPEventType) event.getType(); String methodName = eventType.getCalledMethod(); if( prefixToRemove!=null && methodName.startsWith(prefixToRemove) ) { methodName = methodName.substring(prefixToRemove.length(), methodName.length()); // remove prefix } if( suffixToRemove!=null && methodName.endsWith(suffixToRemove) ) { methodName = methodName.substring(0, methodName.length()-suffixToRemove.length()); } event = new Event(new SimpleSOAPEventType(methodName, eventType.getServiceName(), eventType.getClientName(), eventType.getSoapRequestBody(), eventType.getEqualSOAPDataMap()), event.getTarget()); } normalizedSequence.add(event); } normalizedSequences.add(normalizedSequence); } return normalizedSequences; } /** *

* prevent instantiation *

*/ private SOAPUtils() {} }