View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / eviware.com 
3    *
4    *  SoapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
7    *
8    *  SoapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl;
14  
15  import java.io.IOException;
16  
17  import org.apache.commons.httpclient.Credentials;
18  import org.apache.commons.httpclient.HostConfiguration;
19  import org.apache.commons.httpclient.HttpClient;
20  import org.apache.commons.httpclient.HttpState;
21  import org.apache.commons.httpclient.NTCredentials;
22  import org.apache.commons.httpclient.UsernamePasswordCredentials;
23  import org.apache.commons.httpclient.auth.AuthScheme;
24  import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
25  import org.apache.commons.httpclient.auth.CredentialsProvider;
26  import org.apache.commons.httpclient.auth.NTLMScheme;
27  import org.apache.commons.httpclient.auth.RFC2617Scheme;
28  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
29  import org.apache.commons.httpclient.methods.PostMethod;
30  import org.apache.log4j.Logger;
31  
32  import com.eviware.soapui.impl.wsdl.support.HttpClientSupport;
33  import com.eviware.soapui.model.iface.Request;
34  import com.eviware.soapui.model.iface.Response;
35  import com.eviware.soapui.model.iface.Submit;
36  import com.eviware.soapui.model.iface.SubmitListener;
37  
38  /***
39   * Submit implementation for submitting a WsdlRequest
40   * 
41   * @author Ole.Matzura
42   */
43  
44  public class WsdlSubmit implements Runnable, Submit
45  {
46     private final static Logger logger = Logger.getLogger( WsdlSubmit.class ); 
47     private final WsdlRequest wsdlRequest;
48     private PostMethod postMethod;
49  	private SubmitListener[] listeners;
50  	private String responseContent;
51  	private Status status;
52  	private Exception error;
53  	private WsdlResponse response = new WsdlResponse();
54  	private long timeTaken;
55  	private Thread thread;
56  
57     public WsdlSubmit( WsdlRequest wsdlRequest, SubmitListener [] listeners )
58     {
59        this.wsdlRequest = wsdlRequest;
60  		this.listeners = listeners;
61  		
62  		status = Status.CREATED;
63     }
64     
65     public void submitRequest()
66     {
67  		thread = new Thread( this );
68  		thread.start();
69     }
70  
71     public void cancel()
72     {
73     	if( status == Status.CANCELED ) return;
74        status = Status.CANCELED;
75        
76        logger.info( "Canceling request.." );
77        if( postMethod.isRequestSent() )
78        {
79           postMethod.abort();
80        }
81  
82        status = Status.CANCELED;
83        
84        for (int i = 0; i < listeners.length; i++) {
85  			listeners[i].afterSubmit( this );
86  		}
87     }
88  
89     public void run()
90     {
91        try
92        {
93        	for (int i = 0; i < listeners.length; i++) {
94     			if( !listeners[i].beforeSubmit( this )) return;
95     		}
96  
97        	status = Status.RUNNING;
98        	
99           WsdlInterface wsdlInterface = (WsdlInterface) wsdlRequest.getOperation().getInterface();
100          String strURL = wsdlInterface.getEndpointURL( wsdlRequest.getEndpoint() );
101 
102          postMethod = new PostMethod( strURL );
103          postMethod.getParams().setParameter( CredentialsProvider.PROVIDER, new SoapUICredentialsProvider());
104          postMethod.setDoAuthentication( true );
105          
106          // create new client since we dont want caching of authentications
107          HttpClient httpclient = HttpClientSupport.getHttpClient();
108          String encoding = wsdlRequest.getEncoding();
109          if( encoding != null && encoding.trim().length() == 0) 
110             encoding = null;
111          if( encoding == null  )
112             postMethod.setRequestHeader( "Content-type", "text/xml" );
113          else
114             postMethod.setRequestHeader( "Content-type", "text/xml;charset=" + encoding );
115          
116          String soapAction = wsdlRequest.getOperation().getAction();
117          if( soapAction != null )
118             postMethod.setRequestHeader( "SOAPAction", soapAction );
119 
120          // Request content will be retrieved directly
121          // from the input stream
122          String request = wsdlRequest.getRequestContent();
123          if( request == null ) request = "";
124 
125          byte [] content = encoding == null ? request.getBytes() : request.getBytes( encoding );
126          postMethod.setRequestEntity( new ByteArrayRequestEntity( content ));
127          
128          long now = System.currentTimeMillis();
129          httpclient.executeMethod( new HostConfiguration(), postMethod, new HttpState() );
130          timeTaken = System.currentTimeMillis() - now;
131 			if( status != Status.CANCELED )
132 			{         
133 	         byte[] responseBody = postMethod.getResponseBody();
134 	         responseContent = encoding == null ? new String( responseBody ) : 
135 				            new String( responseBody, encoding );
136 	         
137 	         status = Status.FINISHED;
138 			}
139       }
140       catch( Exception e1 )
141       {
142       	error = e1;
143       	status = Status.ERROR;
144       }
145       finally
146       {
147       	if( postMethod != null )
148       	{
149       		postMethod.releaseConnection();
150       	}
151 
152          if( status != Status.CANCELED )
153          {
154             for (int i = 0; i < listeners.length; i++) {
155       			listeners[i].afterSubmit( this );
156       		}
157          }
158       }
159    }
160 
161 	public Request getRequest() 
162 	{
163 		return wsdlRequest;
164 	}
165 
166 	public String getResponseContent() {
167 		return responseContent;
168 	}
169 
170 	public Status getStatus() {
171 		return status;
172 	}
173 
174 	public Exception getError() {
175 		return error;
176 	}
177 	
178 	private class WsdlResponse implements Response
179 	{
180 		public String getContentAsString() {
181 			try 
182 			{
183 				return postMethod.getResponseBodyAsString();
184 			} 
185 			catch (IOException e) 
186 			{
187 				e.printStackTrace();
188 				return null;
189 			}
190 		}
191 
192 		public long getContentLength() 
193 		{
194 			try {
195 				long length = postMethod.getResponseContentLength();
196 				if (length == -1)
197 					length = postMethod.getResponseBody().length;
198 
199 				return length;
200 			} catch (Exception e) 
201 			{
202 				e.printStackTrace();
203 				return getContentAsString().length();
204 			}
205 		}
206 
207 		public Request getRequest()
208 		{
209 			return wsdlRequest;
210 		}
211 		
212 	}
213 
214 	public Response getResponse( boolean wait )
215 	{
216 		if( wait && (status == Status.RUNNING || status == Status.CREATED) )
217 		{
218 			synchronized (thread)
219 			{
220 				try
221 				{
222 					thread.wait();
223 				}
224 				catch (InterruptedException e)
225 				{
226 					e.printStackTrace();
227 				}
228 			}
229 		}
230 		
231 		return response;
232 	}
233 
234 	public long getTimeTaken() {
235 		return timeTaken;
236 	}
237 	
238 	public class SoapUICredentialsProvider implements CredentialsProvider {
239 
240       public Credentials getCredentials(
241           final AuthScheme authscheme, 
242           final String host, 
243           int port, 
244           boolean proxy)
245           throws CredentialsNotAvailableException 
246       {
247           if (authscheme == null) {
248               return null;
249           }
250           try{
251               if (authscheme instanceof NTLMScheme) {
252                   logger.info(host + ":" + port + " requires Windows authentication");
253                   return new NTCredentials(wsdlRequest.getUsername(), 
254                   		wsdlRequest.getPassword(), host, wsdlRequest.getDomain());    
255               } else
256               if (authscheme instanceof RFC2617Scheme) {
257             	  logger.info(host + ":" + port + " requires authentication with the realm '" 
258                       + authscheme.getRealm() + "'");
259                   return new UsernamePasswordCredentials(wsdlRequest.getUsername(), 
260                   		wsdlRequest.getPassword());    
261               } else {
262                   throw new CredentialsNotAvailableException("Unsupported authentication scheme: " +
263                       authscheme.getSchemeName());
264               }
265           } catch (IOException e) {
266               throw new CredentialsNotAvailableException(e.getMessage(), e);
267           }
268       }
269   }
270 }