Java tutorial
/* * soapUI, copyright (C) 2004-2012 smartbear.com * * soapUI is free software; you can redistribute it and/or modify it under the * terms of version 2.1 of the GNU Lesser General Public License as published by * the Free Software Foundation. * * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details at gnu.org. */ package com.eviware.soapui.impl.wsdl.mock; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.wsdl.Definition; import javax.wsdl.Import; import javax.wsdl.factory.WSDLFactory; import javax.wsdl.xml.WSDLWriter; import org.apache.commons.collections.list.TreeList; import org.apache.log4j.Logger; import org.xml.sax.InputSource; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.WsdlInterfaceFactory; import com.eviware.soapui.impl.support.definition.export.WsdlDefinitionExporter; import com.eviware.soapui.impl.wsdl.WsdlInterface; import com.eviware.soapui.impl.wsdl.WsdlOperation; import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils; import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion; import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext; import com.eviware.soapui.model.iface.Interface; import com.eviware.soapui.model.mock.MockResult; import com.eviware.soapui.model.mock.MockRunListener; import com.eviware.soapui.model.propertyexpansion.PropertyExpander; import com.eviware.soapui.model.support.AbstractMockRunner; import com.eviware.soapui.model.support.ModelSupport; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.Tools; import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler; import com.eviware.soapui.support.types.StringToStringMap; import com.eviware.soapui.support.xml.XmlUtils; /** * MockRunner that dispatches Http Requests to their designated * WsdlMockOperation if possible * * @author ole.matzura */ @SuppressWarnings("unchecked") public class WsdlMockRunner extends AbstractMockRunner { private WsdlMockService mockService; private final List<WsdlMockResult> mockResults = Collections.synchronizedList(new TreeList()); private long maxResults = 100; private int removed = 0; private final WsdlMockRunContext mockContext; private final Map<String, StringToStringMap> wsdlCache = new HashMap<String, StringToStringMap>(); private boolean running; private boolean logEnabled = true; private final static Logger log = Logger.getLogger(WsdlMockRunner.class); public WsdlMockRunner(WsdlMockService mockService, WsdlTestRunContext context) throws Exception { this.mockService = mockService; Set<WsdlInterface> interfaces = new HashSet<WsdlInterface>(); for (int i = 0; i < mockService.getMockOperationCount(); i++) { WsdlOperation operation = mockService.getMockOperationAt(i).getOperation(); if (operation != null) interfaces.add(operation.getInterface()); } for (WsdlInterface iface : interfaces) iface.getWsdlContext().loadIfNecessary(); initWsdlCache(); mockContext = new WsdlMockRunContext(mockService, context); start(); } private void initWsdlCache() { for (Interface iface : mockService.getMockedInterfaces()) { if (!iface.getInterfaceType().equals(WsdlInterfaceFactory.WSDL_TYPE)) continue; try { WsdlDefinitionExporter exporter = new WsdlDefinitionExporter((WsdlInterface) iface); String wsdlPrefix = getInterfacePrefix(iface).substring(1); StringToStringMap parts = exporter.createFilesForExport("/" + wsdlPrefix + "&part="); for (String key : parts.keySet()) { if (key.toLowerCase().endsWith(".wsdl")) { InputSource inputSource = new InputSource(new StringReader(parts.get(key))); String content = WsdlUtils.replacePortEndpoint((WsdlInterface) iface, inputSource, mockService.getLocalMockServiceEndpoint()); if (content != null) parts.put(key, content); } } wsdlCache.put(iface.getName(), parts); log.info("Mounted WSDL for interface [" + iface.getName() + "] at [" + getOverviewUrl() + "]"); } catch (Exception e) { SoapUI.logError(e); } } } public String getInterfacePrefix(Interface iface) { String wsdlPrefix = getOverviewUrl() + "&interface=" + iface.getName(); return wsdlPrefix; } public WsdlMockRunContext getMockContext() { return mockContext; } public synchronized void addMockResult(WsdlMockResult mockResult) { if (maxResults > 0 && logEnabled) mockResults.add(mockResult); while (mockResults.size() > maxResults) { mockResults.remove(0); removed++; } } public boolean isRunning() { return running; } public void stop() { if (!isRunning()) return; SoapUI.getMockEngine().stopMockService(this); MockRunListener[] mockRunListeners = mockService.getMockRunListeners(); for (MockRunListener listener : mockRunListeners) { listener.onMockRunnerStop(this); } try { mockService.runStopScript(mockContext, this); running = false; } catch (Exception e) { SoapUI.logError(e); } } public WsdlMockService getMockService() { return mockService; } public long getMaxResults() { return maxResults; } public synchronized void setMaxResults(long l) { this.maxResults = l; while (mockResults.size() > l) { mockResults.remove(0); removed++; } } @Override public MockResult dispatchHeadRequest(HttpServletRequest request, HttpServletResponse response) throws DispatchException { response.setStatus(HttpServletResponse.SC_OK); return null; } public WsdlMockResult dispatchPostRequest(WsdlMockRequest mockRequest) throws Exception { WsdlMockResult result = null; try { long timestamp = System.currentTimeMillis(); SoapVersion soapVersion = mockRequest.getSoapVersion(); if (soapVersion == null) throw new DispatchException("Unrecognized SOAP Version"); String soapAction = mockRequest.getSoapAction(); WsdlOperation operation = null; if (SoapUtils.isSoapFault(mockRequest.getRequestContent(), soapVersion)) { // we should inspect fault detail and try to find matching operation // but not for now.. WsdlMockOperation faultMockOperation = mockService.getFaultMockOperation(); if (faultMockOperation != null) operation = faultMockOperation.getOperation(); } else { try { operation = SoapUtils.findOperationForRequest(soapVersion, soapAction, mockRequest.getRequestXmlObject(), mockService.getMockedOperations(), mockService.isRequireSoapVersion(), mockService.isRequireSoapAction(), mockRequest.getRequestAttachments()); } catch (Exception e) { if (mockService.isDispatchResponseMessages()) { try { operation = SoapUtils.findOperationForResponse(soapVersion, soapAction, mockRequest.getRequestXmlObject(), mockService.getMockedOperations(), mockService.isRequireSoapVersion(), mockService.isRequireSoapAction()); if (operation != null) { mockRequest.setResponseMessage(true); } } catch (Exception e2) { throw e; } } else { throw e; } } } if (operation != null) { WsdlMockOperation mockOperation = mockService.getMockOperation(operation); if (mockOperation != null) { long startTime = System.nanoTime(); // try // { result = mockOperation.dispatchRequest(mockRequest); // } // catch( DispatchException e ) // { // result = new WsdlMockResult( mockRequest ); // // String fault = SoapMessageBuilder.buildFault( "Server", // e.getMessage(), mockRequest.getSoapVersion() ); // result.setResponseContent( fault ); // result.setMockOperation( mockOperation ); // // mockRequest.getHttpResponse().getWriter().write( fault ); // } if (mockRequest.getHttpRequest() instanceof org.mortbay.jetty.Request) ((org.mortbay.jetty.Request) mockRequest.getHttpRequest()).setHandled(true); result.setTimeTaken((System.nanoTime() - startTime) / 1000000); result.setTimestamp(timestamp); addMockResult(result); return result; } else { throw new DispatchException("Failed to find matching operation for request"); } } throw new DispatchException("Missing operation for soapAction [" + soapAction + "] and body element [" + XmlUtils.getQName(mockRequest.getContentElement()) + "] with SOAP Version [" + mockRequest.getSoapVersion() + "]"); } catch (Exception e) { if (e instanceof DispatchException) throw (DispatchException) e; throw new DispatchException(e); } } public MockResult getMockResultAt(int index) { return index <= removed ? null : mockResults.get(index - removed); } public int getMockResultCount() { return mockResults.size() + removed; } public synchronized void clearResults() { mockResults.clear(); } public void release() { clearResults(); mockService = null; mockContext.clear(); } @Override public MockResult dispatchRequest(HttpServletRequest request, HttpServletResponse response) throws DispatchException { Object result = null; try { for (MockRunListener listener : mockService.getMockRunListeners()) { result = listener.onMockRequest(this, request, response); if (result instanceof MockResult) return (MockResult) result; } WsdlMockRequest mockRequest = new WsdlMockRequest(request, response, mockContext); result = mockService.runOnRequestScript(mockContext, this, mockRequest); if (!(result instanceof MockResult)) { String method = mockRequest.getMethod(); if (method.equals("POST")) result = dispatchPostRequest(mockRequest); else result = super.dispatchRequest(request, response); } mockService.runAfterRequestScript(mockContext, this, (MockResult) result); return (MockResult) result; } catch (Throwable e) { if (e instanceof DispatchException) throw (DispatchException) e; else throw new DispatchException(e); } finally { if (result instanceof MockResult) { for (MockRunListener listener : mockService.getMockRunListeners()) { listener.onMockResult((MockResult) result); } } } } public MockResult dispatchGetRequest(HttpServletRequest request, HttpServletResponse response) throws DispatchException { try { String qs = request.getQueryString(); if (qs != null && qs.toUpperCase().startsWith("WSDL")) { dispatchWsdlRequest(request, response); } else { if (qs != null && qs.startsWith("cmd=")) { dispatchCommand(request.getParameter("cmd"), request, response); } else { String docroot = PropertyExpander.expandProperties(mockContext, getMockService().getDocroot()); if (StringUtils.hasContent(docroot)) { try { String pathInfo = request.getPathInfo(); if (pathInfo == null) pathInfo = ""; if (mockService.getPath().length() > 1 && pathInfo.startsWith(mockService.getPath())) pathInfo = pathInfo.substring(mockService.getPath().length()); String filename = docroot + pathInfo.replace('/', File.separatorChar); File file = new File(filename); if (file.exists()) { returnFile(response, file); } } catch (Throwable e) { throw new DispatchException(e); } } } } return null; } catch (Exception e) { throw new DispatchException(e); } } public void returnFile(HttpServletResponse response, File file) throws FileNotFoundException, IOException { FileInputStream in = new FileInputStream(file); response.setStatus(HttpServletResponse.SC_OK); long length = file.length(); response.setContentLength((int) length); response.setContentType(ContentTypeHandler.getContentTypeFromFilename(file.getName())); Tools.readAndWrite(in, length, response.getOutputStream()); in.close(); } private void dispatchCommand(String cmd, HttpServletRequest request, HttpServletResponse response) throws IOException { if ("stop".equals(cmd)) { response.setStatus(HttpServletResponse.SC_OK); response.flushBuffer(); SoapUI.getThreadPool().execute(new Runnable() { public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } stop(); } }); } else if ("restart".equals(cmd)) { response.setStatus(HttpServletResponse.SC_OK); response.flushBuffer(); SoapUI.getThreadPool().execute(new Runnable() { public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } stop(); // // try // { // Thread.sleep( 500 ); // } // catch( InterruptedException e ) // { // e.printStackTrace(); // } try { mockService.start(); } catch (Exception e) { e.printStackTrace(); } } }); } } protected void dispatchWsdlRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { if (request.getQueryString().equalsIgnoreCase("WSDL")) { printWsdl(response); return; } String ifaceName = request.getParameter("interface"); WsdlInterface iface = (WsdlInterface) mockService.getProject().getInterfaceByName(ifaceName); if (iface == null) { printInterfaceList(response); return; } StringToStringMap parts = wsdlCache.get(iface.getName()); String part = request.getParameter("part"); String content = StringUtils.isNullOrEmpty(part) ? null : parts.get(part); if (content == null) { printPartList(iface, parts, response); return; } if (content != null) { printOkXmlResult(response, content); } } public void printOkXmlResult(HttpServletResponse response, String content) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); response.getWriter().print(content); } public void printWsdl(HttpServletResponse response) throws IOException { WsdlInterface[] mockedInterfaces = mockService.getMockedInterfaces(); if (mockedInterfaces.length == 1) { StringToStringMap parts = wsdlCache.get(mockedInterfaces[0].getName()); printOkXmlResult(response, parts.get(parts.get("#root#"))); } else { try { WSDLFactory wsdlFactory = WSDLFactory.newInstance(); Definition def = wsdlFactory.newDefinition(); for (WsdlInterface iface : mockedInterfaces) { StringToStringMap parts = wsdlCache.get(iface.getName()); Import wsdlImport = def.createImport(); wsdlImport.setLocationURI(getInterfacePrefix(iface) + "&part=" + parts.get("#root#")); wsdlImport .setNamespaceURI(WsdlUtils.getTargetNamespace(iface.getWsdlContext().getDefinition())); def.addImport(wsdlImport); } response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); WSDLWriter writer = wsdlFactory.newWSDLWriter(); writer.writeWSDL(def, response.getWriter()); } catch (Exception e) { SoapUI.logError(e); throw new IOException("Failed to create combined WSDL"); } } } public void printPartList(WsdlInterface iface, StringToStringMap parts, HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("<html><body><p>Parts in interface [" + iface.getName() + "]</p><ul>"); for (String key : parts.keySet()) { if (key.equals("#root#")) continue; out.print("<li><a href=\""); out.print(getInterfacePrefix(iface) + "&part=" + key); out.print("\">" + key + "</a></li>"); } out.print("</ul></p></body></html>"); } public void printInterfaceList(HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print( "<html><body><p>Mocked Interfaces in project [" + mockService.getProject().getName() + "]</p><ul>"); for (Interface iface : ModelSupport.getChildren(mockService.getProject(), WsdlInterface.class)) { out.print("<li><a href=\""); out.print(getInterfacePrefix(iface)); out.print("\">" + iface.getName() + "</a></li>"); } out.print("</ul></p></body></html>"); } public String getOverviewUrl() { return mockService.getPath() + "?WSDL"; } public void setLogEnabled(boolean logEnabled) { this.logEnabled = logEnabled; } public void start() throws Exception { if (running) return; mockContext.reset(); mockService.runStartScript(mockContext, this); SoapUI.getMockEngine().startMockService(this); running = true; MockRunListener[] mockRunListeners = mockService.getMockRunListeners(); for (MockRunListener listener : mockRunListeners) { listener.onMockRunnerStart(this); } } }