1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.monitor;
14
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.log4j.Logger;
28 import org.mortbay.jetty.HttpConnection;
29 import org.mortbay.jetty.Server;
30 import org.mortbay.jetty.handler.AbstractHandler;
31 import org.mortbay.jetty.nio.SelectChannelConnector;
32 import org.mortbay.thread.BoundedThreadPool;
33
34 import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
35 import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner;
36 import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
37 import com.eviware.soapui.model.mock.MockRunner;
38 import com.eviware.soapui.model.mock.MockService;
39 import com.eviware.soapui.support.UISupport;
40 import com.eviware.soapui.support.log.JettyLogger;
41
42 public class MockEngine
43 {
44 private final static Logger log = Logger.getLogger( MockEngine.class );
45
46 private Server server;
47 private Map<Integer, Map<String,MockRunner> > runners = new HashMap<Integer, Map<String,MockRunner> >();
48 private Map<Integer, SoapUIConnector> connectors = new HashMap<Integer,SoapUIConnector>();
49 private List<MockRunner> mockRunners = new ArrayList<MockRunner>();
50
51 public MockEngine()
52 {
53 System.setProperty( "org.mortbay.log.class", JettyLogger.class.getName() );
54 }
55
56 public boolean hasRunningMock( MockService mockService )
57 {
58 return false;
59 }
60
61 public void startMockService( MockRunner runner ) throws Exception
62 {
63 if( server == null )
64 initServer();
65
66 MockService mockService = runner.getMockService();
67 int port = mockService.getPort();
68
69 if( !runners.containsKey( port ))
70 {
71 SoapUIConnector connector = new SoapUIConnector();
72
73 connector.setPort( port );
74 boolean wasRunning = server.isRunning();
75
76 if( wasRunning )
77 {
78 server.stop();
79 }
80
81 server.addConnector( connector );
82 try
83 {
84 server.start();
85 }
86 catch( RuntimeException e )
87 {
88 e.printStackTrace();
89 UISupport.showErrorMessage( e );
90
91 server.removeConnector( connector );
92 if( wasRunning )
93 {
94 server.start();
95 return;
96 }
97 }
98
99 connectors.put( new Integer( port), connector );
100 runners.put( new Integer( port), new HashMap<String,MockRunner>() );
101 }
102
103 Map<String, MockRunner> map = runners.get( port );
104 String path = mockService.getPath();
105 map.put( path, runner );
106 mockRunners.add( runner );
107
108 log.info( "Started mockService [" + mockService.getName() + "] on port [" + port + "] at path [" + path + "]" );
109 }
110
111 private void initServer() throws Exception
112 {
113 server = new Server();
114 BoundedThreadPool threadPool = new BoundedThreadPool();
115 threadPool.setMaxThreads( 100 );
116 server.setThreadPool( threadPool );
117
118 server.setHandler( new ServerHandler() );
119 }
120
121 public void stopMockService( WsdlMockRunner runner )
122 {
123 MockService mockService = runner.getMockService();
124 final Integer port = new Integer( mockService.getPort());
125 Map<String, MockRunner> map = runners.get( port );
126
127 map.remove( mockService.getPath() );
128 mockRunners.remove( runner );
129
130 if( map.isEmpty() )
131 {
132 SoapUIConnector connector = ( SoapUIConnector ) connectors.get( port );
133 if( connector == null )
134 {
135 log.warn( "Missing connectors on port [" + port + "]" );
136 return;
137 }
138
139 try
140 {
141 log.info( "Stopping connector on port " + port );
142 if( !connector.waitUntilIdle( 5000 ))
143 {
144 log.warn( "Failed to wait for idle.. stopping connector anyway.." );
145 }
146 connector.stop();
147 }
148 catch( Exception e )
149 {
150 e.printStackTrace();
151 }
152 server.removeConnector( connector );
153 runners.remove( port );
154 if( runners.isEmpty() )
155 {
156 try
157 {
158 log.info( "No more connectors.. stopping server" );
159 server.stop();
160 }
161 catch( Exception e )
162 {
163 e.printStackTrace();
164 }
165 }
166 }
167 }
168
169 private class SoapUIConnector extends SelectChannelConnector
170 {
171 private Set<HttpConnection> connections = new HashSet<HttpConnection>();
172
173 @Override
174 protected void connectionClosed( HttpConnection arg0 )
175 {
176 super.connectionClosed( arg0 );
177 connections.remove( arg0 );
178 }
179
180 @Override
181 protected void connectionOpened( HttpConnection arg0 )
182 {
183 super.connectionOpened( arg0 );
184 connections.add( arg0 );
185 }
186
187 public boolean waitUntilIdle( long maxwait ) throws Exception
188 {
189 while( maxwait > 0 && hasActiveConnections() )
190 {
191 System.out.println( "Waiting for active connections to finish.." );
192 Thread.sleep( 500 );
193 maxwait -= 500;
194 }
195
196 return !hasActiveConnections();
197 }
198
199 private boolean hasActiveConnections()
200 {
201 for( HttpConnection connection : connections )
202 {
203 if( !connection.isIdle() )
204 return true;
205 }
206
207 return false;
208 }
209 }
210
211 private class ServerHandler extends AbstractHandler
212 {
213 public void handle( String target, HttpServletRequest request,
214 HttpServletResponse response, int dispatch ) throws IOException, ServletException
215 {
216
217 Map<String, MockRunner> map = runners.get( request.getLocalPort() );
218 if( map != null )
219 {
220 MockRunner wsdlMockRunner = map.get( request.getPathInfo() );
221 if( wsdlMockRunner != null )
222 {
223 try
224 {
225 WsdlMockResult result = ( WsdlMockResult ) wsdlMockRunner.dispatchRequest( request, response );
226 result.finish();
227 }
228 catch( Exception e )
229 {
230 e.printStackTrace();
231
232 SoapMessageBuilder messageBuilder = ( SoapMessageBuilder ) wsdlMockRunner.getMockService().getProject().getInterfaceAt( 0 ).getMessageBuilder();
233 response.getWriter().print( messageBuilder.buildFault( "Server", e.getMessage() ));
234
235 throw new ServletException( e );
236 }
237 }
238 }
239 }
240 }
241
242 public MockRunner [] getMockRunners()
243 {
244 return mockRunners.toArray( new MockRunner[mockRunners.size()] );
245 }
246 }