/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.mockaswar; import com.eviware.soapui.DefaultSoapUICore; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.mock.DispatchException; import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner; import com.eviware.soapui.impl.wsdl.mock.WsdlMockService; import com.eviware.soapui.model.mock.MockResult; import com.eviware.soapui.model.mock.MockRunner; import com.eviware.soapui.model.mock.MockService; import com.eviware.soapui.model.project.ProjectFactoryRegistry; import com.eviware.soapui.monitor.MockEngine; import com.eviware.soapui.support.SoapUIException; 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.StringToStringsMap; import com.eviware.soapui.support.xml.XmlUtils; import org.apache.commons.collections.list.TreeList; import org.apache.log4j.spi.LoggingEvent; import org.apache.xmlbeans.XmlException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Servlet implementation class SoapUIMockServlet */ @SuppressWarnings("unchecked") public class MockAsWarServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected static Logger logger = Logger.getLogger(MockAsWarServlet.class.getName()); protected WsdlProject project; long maxResults; List<MockResult> results = new TreeList(); private List<LoggingEvent> events = new TreeList(); boolean enableWebUI; public void init() throws ServletException { super.init(); try { SoapUI.setSoapUICore(new MockServletSoapUICore(getServletContext()), true); String mockServiceEndpoint = initMockServiceParameters(); logger.info("Loading project"); initProject(getServletContext().getRealPath(getInitParameter("projectFile"))); if (project == null || project.getName() == null) { initProject(getServletContext().getResource("/" + getInitParameter("projectFile")).toString()); } if (project == null) { logger.info("Starting Mock service(s)"); } for (MockService mockService : project.getMockServiceList()) { logger.info("Starting mock service [" + mockService.getName() + "]"); if (StringUtils.hasContent(mockServiceEndpoint)) { ((WsdlMockService) mockService).setMockServiceEndpoint(mockServiceEndpoint); } mockService.start(); } for (MockService mockService : project.getRestMockServiceList()) { logger.info("Starting REST mock service [" + mockService.getName() + "]"); mockService.start(); } } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); } } protected void initProject(String path) throws XmlException, IOException, SoapUIException { project = (WsdlProject) ProjectFactoryRegistry.getProjectFactory("wsdl").createNew(path); } protected String initMockServiceParameters() { try { if (StringUtils.hasContent(getInitParameter("listeners"))) { logger.info("Init listeners"); try { System.setProperty("soapui.ext.listeners", getServletContext().getRealPath(getInitParameter("listeners"))); } catch (Exception e) { logger.info("Listeners not set! Reason : " + e.getMessage()); } } else { logger.info("Listeners not set!"); } if (StringUtils.hasContent(getInitParameter("actions"))) { logger.info("Init actions"); try { System.setProperty("soapui.ext.actions", getServletContext().getRealPath(getInitParameter("actions"))); } catch (Exception e) { logger.info("Actions not set! Reason : " + e.getMessage()); } } else { logger.info("Actions not set!"); } if (SoapUI.getSoapUICore() == null) { if (StringUtils.hasContent(getInitParameter("soapUISettings"))) { logger.info("Init settings"); SoapUI.setSoapUICore( new MockServletSoapUICore(getServletContext(), getInitParameter("soapUISettings")), true); } else { logger.info("Settings not set!"); SoapUI.setSoapUICore(new MockServletSoapUICore(getServletContext()), true); } } else { logger.info("SoapUI core already exists, reusing existing one"); } if (StringUtils.hasContent(getInitParameter("enableWebUI"))) { if ("true".equals(getInitParameter("enableWebUI"))) { logger.info("WebUI ENABLED"); enableWebUI = true; } else { logger.info("WebUI DISABLED"); enableWebUI = false; } } }catch (Exception e){ logger.info("Property set with error!"+e.getMessage()); } try { maxResults = Integer.parseInt(getInitParameter("maxResults")); } catch (NumberFormatException ex) { maxResults = 1000; } SoapUI.ensureGroovyLog().addAppender(new GroovyLogAppender()); return getInitParameter("mockServiceEndpoint"); } public void destroy() { super.destroy(); getMockServletCore().stop(); } protected MockAsWarCoreInterface getMockServletCore() { return (MockAsWarCoreInterface) SoapUI.getSoapUICore(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { getMockServletCore().dispatchRequest(request, response); } catch (DispatchException ex) { logger.log(Level.SEVERE, null, ex); } } private void printResult(PrintWriter out, MockResult result) { out.print("<h4>Details for MockResult at " + new java.util.Date(result.getTimestamp()) + " (" + result.getTimeTaken() + "ms)</h4>"); out.println("<hr/><p><b>Request Headers</b>:</p>"); out.print("<table border=\"1\"><tr><td>Header</td><td>Value</td></tr>"); StringToStringsMap headers = result.getMockRequest().getRequestHeaders(); for (String name : headers.getKeys()) { for (String value : headers.get(name)) { out.println("<tr><td>" + name + "</td><td>" + value + "</td></tr>"); } } out.println("</table>"); out.println("<hr/><b>Incoming Request</b>:<br/><pre>" + XmlUtils.entitize(result.getMockRequest().getRequestContent()) + "</pre>"); out.println("<hr/><p><b>Response Headers</b>:</p>"); out.print("<table border\"1\"><tr><td>Header</td><td>Value</td></tr>"); headers = result.getResponseHeaders(); for (String name : headers.getKeys()) { for (String value : headers.get(name)) { out.println("<tr><td>" + name + "</td><td>" + value + "</td></tr>"); } } out.println("</table>"); out.println("<hr/><b>Returned Response</b>:<pre>" + XmlUtils.entitize(result.getResponseContent()) + "</pre>"); } class MockServletSoapUICore extends DefaultSoapUICore implements MockEngine, MockAsWarCoreInterface { private final ServletContext servletContext; private List<MockRunner> mockRunners = new ArrayList<MockRunner>(); public MockServletSoapUICore(ServletContext servletContext, String soapUISettings) { super(servletContext.getRealPath("/"), servletContext.getRealPath(soapUISettings)); this.servletContext = servletContext; } /* * (non-Javadoc) * * @see * com.eviware.soapui.mockaswar.MockAsWarCoreInterface#dispatchRequest * (javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public void dispatchRequest(HttpServletRequest request, HttpServletResponse response) throws DispatchException, IOException { String pathInfo = request.getPathInfo(); if (pathInfo == null) { pathInfo = ""; } MockRunner mockRunner = getMatchedMockRunner(getMockRunners(), pathInfo); if (mockRunner != null) { MockResult result = mockRunner.dispatchRequest(request, response); if (maxResults > 0) { synchronized (results) { while (maxResults > 0 && results.size() > maxResults) { results.remove(0); } if (result != null) { results.add(result); } } } return; } if (enableWebUI) { String realPath = servletContext.getRealPath(pathInfo); File file = realPath == null ? null : new File(realPath); if (file != null && file.exists() && file.isFile()) { 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(); } else if (pathInfo.equals("/master")) { printMaster(request, response, mockRunners); } else if (pathInfo.equals("/detail")) { printDetail(request, response); } else if (pathInfo.equals("/log")) { printLog(request, response); } else { printFrameset(request, response); } } else { printDisabledLogFrameset(request, response); } } private MockRunner getMatchedMockRunner(MockRunner[] mockRunners, String pathInfo) { MockRunner mockRunner = null; String bestMatchedRootPath = ""; for (MockRunner runner : mockRunners) { String mockServicePath = runner.getMockContext().getMockService().getPath(); if (pathInfo.startsWith(mockServicePath) && mockServicePath.length() > bestMatchedRootPath.length()) { bestMatchedRootPath = mockServicePath; mockRunner = runner; } } return mockRunner; } /* * (non-Javadoc) * * @see com.eviware.soapui.mockaswar.MockAsWarCoreInterface#stop() */ @Override public void stop() { for (MockRunner mockRunner : getMockRunners()) { mockRunner.stop(); } } public MockServletSoapUICore(ServletContext servletContext) { super(servletContext.getRealPath("/"), null); this.servletContext = servletContext; } @Override protected MockEngine buildMockEngine() { return this; } public MockRunner[] getMockRunners() { return mockRunners.toArray(new MockRunner[mockRunners.size()]); } public boolean hasRunningMock(MockService mockService) { for (MockRunner runner : mockRunners) { if (runner.getMockContext().getMockService() == mockService) { return true; } } return false; } public void startMockService(MockRunner runner) throws Exception { mockRunners.add(runner); } public void stopMockService(MockRunner runner) { mockRunners.remove(runner); } } public void printMaster(HttpServletRequest request, HttpServletResponse response, List<MockRunner> mockRunners) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); startHtmlPage(out, "MockService Log Table", "15"); out.print("<img src=\"header_logo.png\"><h3>SoapUI MockServices Log for project [" + project.getName() + "]</h3>" + "<p style=\"text-align: left\">WSDLs:"); for (MockRunner mockRunner : mockRunners) { String overviewUrl = ((WsdlMockRunner) mockRunner).getOverviewUrl(); if (overviewUrl.startsWith("/")) { overviewUrl = overviewUrl.substring(1); } out.print(" [<a target=\"new\" href=\"" + overviewUrl + "\">" + mockRunner.getMockContext().getMockService().getName() + "</a>]"); } out.print("</p>"); out.print("<hr/><p><b>Processed Requests</b>: "); out.print("[<a href=\"master\">Refresh</a>] "); out.print("[<a href=\"master?clear\">Clear</a>]</p>"); if ("clear".equals(request.getQueryString())) { results.clear(); } out.print("<table border=\"1\">"); out.print("<tr><td></td><td>Timestamp</td><td>Time Taken</td><td>MockOperation</td><td>MockResponse</td><td>MockService</td></tr>"); int cnt = 1; for (MockResult result : results) { if (result != null) { out.print("<tr><td>" + (cnt++) + "</td>"); out.print("<td><a target=\"detail\" href=\"detail?" + result.hashCode() + "\">" + new java.util.Date(result.getTimestamp()) + "</a></td>"); out.print("<td>" + result.getTimeTaken() + "</td>"); out.print("<td>" + result.getMockOperation().getName() + "</td>"); if (result.getMockResponse() != null) { out.print("<td>" + result.getMockResponse().getName() + "</td>"); } out.print("<td>" + result.getMockOperation().getMockService().getName() + "</td></tr>"); } } out.print("</table>"); out.print("</body></html>"); out.flush(); } private void startHtmlPage(PrintWriter out, String title, String refresh) { out.print("<html><head>"); out.print("<title>" + title + "</title>"); if (refresh != null) { out.print("<meta http-equiv=\"refresh\" content=\"" + refresh + "\"/>"); } out.print("<link type=\"text/css\" rel=\"stylesheet\" href=\"stylesheet.css\" />"); out.print("</head><body>"); } public void printDisabledLogFrameset(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("<html><head><title>SoapUI MockServices Log for project [" + project.getName() + "]</title></head>"); out.print("<body>"); out.print("<h3>"); out.print("Log is disabled."); out.print("</h3>"); out.print("</body></html>"); out.flush(); } public void printFrameset(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("<html><head><title>SoapUI MockServices Log for project [" + project.getName() + "]</title></head>"); out.print("<frameset rows=\"40%,40%,*\">"); out.print("<frame src=\"master\"/>"); out.print("<frame name=\"detail\" src=\"detail\"/>"); out.print("<frame src=\"log\"/>"); out.print("</frameset>"); out.print("</html>"); out.flush(); } public void printDetail(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); startHtmlPage(out, "MockService Detail", null); int id = 0; try { id = Integer.parseInt(request.getQueryString()); } catch (NumberFormatException e) { } if (id > 0) { for (MockResult result : results) { if (result.hashCode() == id) { id = 0; printResult(out, result); } } } if (id > 0) { out.print("<p>Missing specified MockResult</p>"); } out.print("</body></html>"); out.flush(); } private class GroovyLogAppender extends org.apache.log4j.AppenderSkeleton { protected void append(LoggingEvent event) { events.add(event); } public void close() { } public boolean requiresLayout() { return false; } } public void printLog(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html"); PrintWriter out = response.getWriter(); startHtmlPage(out, "MockService Groovy Log", "15"); out.print("<p><b>Groovy Log output</b>: "); out.print("[<a href=\"log\">Refresh</a>] "); out.print("[<a href=\"log?clear\">Clear</a>]</p>"); if ("clear".equals(request.getQueryString())) { events.clear(); } out.print("<table border=\"1\">"); out.print("<tr><td></td><td>Timestamp</td><td>Message</td></tr>"); int cnt = 1; for (LoggingEvent event : events) { out.print("<tr><td>" + (cnt++) + "</td>"); out.print("<td>" + new java.util.Date(event.timeStamp) + "</td>"); out.print("<td>" + event.getRenderedMessage() + "</td></tr>"); } out.print("</table>"); out.print("</body></html>"); out.flush(); } }