View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
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.endpoint;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.util.Arrays;
18  import java.util.HashMap;
19  import java.util.HashSet;
20  import java.util.Map;
21  import java.util.Set;
22  
23  import javax.swing.JComponent;
24  
25  import org.apache.commons.httpclient.HttpMethod;
26  import org.apache.commons.httpclient.URI;
27  import org.apache.commons.httpclient.URIException;
28  
29  import com.eviware.soapui.SoapUI;
30  import com.eviware.soapui.config.DefaultEndpointStrategyConfig;
31  import com.eviware.soapui.config.EndpointConfig;
32  import com.eviware.soapui.config.ProjectConfig;
33  import com.eviware.soapui.impl.support.AbstractInterface;
34  import com.eviware.soapui.impl.wsdl.WsdlProject;
35  import com.eviware.soapui.impl.wsdl.WsdlRequest;
36  import com.eviware.soapui.impl.wsdl.submit.filters.HttpAuthenticationRequestFilter;
37  import com.eviware.soapui.impl.wsdl.submit.filters.WssAuthenticationRequestFilter;
38  import com.eviware.soapui.impl.wsdl.submit.transports.http.BaseHttpRequestTransport;
39  import com.eviware.soapui.model.iface.Interface;
40  import com.eviware.soapui.model.iface.Request;
41  import com.eviware.soapui.model.iface.Response;
42  import com.eviware.soapui.model.iface.SubmitContext;
43  import com.eviware.soapui.model.project.EndpointStrategy;
44  import com.eviware.soapui.model.project.Project;
45  import com.eviware.soapui.model.project.ProjectListener;
46  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
47  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
48  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
49  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
50  import com.eviware.soapui.model.support.ProjectListenerAdapter;
51  import com.eviware.soapui.support.StringUtils;
52  import com.eviware.soapui.support.types.StringList;
53  
54  public class DefaultEndpointStrategy implements EndpointStrategy, PropertyExpansionContainer
55  {
56  	private WsdlProject project;
57  	private DefaultEndpointStrategyConfig config;
58  	private Map<String, EndpointDefaults> defaults = new HashMap<String, EndpointDefaults>();
59  	private PropertyChangeListener propertyChangeListener = new InternalPropertyChangeListener();
60  	private ProjectListener projectListener = new InternalProjectListener();
61  
62  	public void init( Project project )
63  	{
64  		this.project = ( WsdlProject ) project;
65  		initConfig();
66  
67  		project.addProjectListener( projectListener );
68  
69  		for( Interface iface : project.getInterfaceList() )
70  		{
71  			for( String endpoint : iface.getEndpoints() )
72  			{
73  				// ensure we have defaults
74  				getEndpointDefaults( endpoint );
75  			}
76  
77  			iface.addPropertyChangeListener( AbstractInterface.ENDPOINT_PROPERTY, propertyChangeListener );
78  		}
79  
80  		removeUnusedEndpoints();
81  	}
82  
83  	private void initConfig()
84  	{
85  		ProjectConfig projectConfig = this.project.getConfig();
86  
87  		if( !projectConfig.isSetEndpointStrategy() )
88  		{
89  			projectConfig.addNewEndpointStrategy();
90  		}
91  
92  		config = ( DefaultEndpointStrategyConfig ) projectConfig.getEndpointStrategy().changeType(
93  					DefaultEndpointStrategyConfig.type );
94  
95  		for( EndpointConfig endpointConfig : config.getEndpointList() )
96  		{
97  			defaults.put( endpointConfig.getStringValue(), new EndpointDefaults( endpointConfig ) );
98  		}
99  	}
100 
101 	private void removeUnusedEndpoints()
102 	{
103 		if( config == null )
104 			return;
105 
106 		Set<String> endpoints = new HashSet<String>();
107 
108 		for( Interface iface : project.getInterfaceList() )
109 		{
110 			endpoints.addAll( Arrays.asList( iface.getEndpoints() ) );
111 		}
112 
113 		StringList keys = new StringList();
114 
115 		for( String key : defaults.keySet() )
116 		{
117 			if( !endpoints.contains( key ) )
118 			{
119 				keys.add( key );
120 			}
121 		}
122 
123 		for( String key : keys )
124 		{
125 			EndpointDefaults def = defaults.remove( key );
126 			config.getEndpointList().remove( def );
127 		}
128 	}
129 
130 	public void filterRequest( SubmitContext context, Request wsdlRequest )
131 	{
132 		HttpMethod httpMethod = ( HttpMethod ) context.getProperty( BaseHttpRequestTransport.HTTP_METHOD );
133 		URI uri = null;
134 		try
135 		{
136 			uri = httpMethod.getURI();
137 		}
138 		catch( URIException e )
139 		{
140 			SoapUI.logError( e );
141 			return;
142 		}
143 
144 		EndpointDefaults def = defaults.get( uri.toString() );
145 		
146 		if( def == null )
147 		{
148 			for( String ep : defaults.keySet() )
149 			{
150 				if( PropertyExpansionUtils.expandProperties(context, ep).equals(uri.toString()) )
151 				{
152 					def = defaults.get(ep);
153 					break;
154 				}
155 			}
156 			
157 			if( def == null )
158 				return;
159 		}
160 
161 		applyDefaultsToWsdlRequest( context, (WsdlRequest) wsdlRequest, def );
162 	}
163 
164 	protected void applyDefaultsToWsdlRequest( SubmitContext context, WsdlRequest wsdlRequest, EndpointDefaults def )
165 	{
166 		String requestUsername = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getUsername() );
167 		String requestPassword = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getPassword() );
168 		String requestDomain = PropertyExpansionUtils.expandProperties( context, wsdlRequest.getDomain() );
169 
170 		String defUsername = PropertyExpansionUtils.expandProperties( context, def.getUsername() );
171 		String defPassword = PropertyExpansionUtils.expandProperties( context, def.getPassword() );
172 		String defDomain = PropertyExpansionUtils.expandProperties( context, def.getDomain() );
173 
174 		if( def.getMode() == EndpointConfig.Mode.OVERRIDE )
175 		{
176 			overrideRequest( context, wsdlRequest, def, requestUsername, requestPassword, requestDomain, defUsername,
177 						defPassword, defDomain );
178 		}
179 		else if( def.getMode() == EndpointConfig.Mode.COPY )
180 		{
181 			copyToRequest( context, wsdlRequest, def, requestUsername, requestPassword, requestDomain, defUsername,
182 						defPassword, defDomain );
183 		}
184 		else if( def.getMode() == EndpointConfig.Mode.COMPLEMENT )
185 		{
186 			complementRequest( context, wsdlRequest, def, requestUsername, requestPassword, requestDomain, defUsername,
187 						defPassword, defDomain );
188 		}
189 	}
190 
191 	private void overrideRequest( SubmitContext context, WsdlRequest wsdlRequest, EndpointDefaults def,
192 				String requestUsername, String requestPassword, String requestDomain, String defUsername,
193 				String defPassword, String defDomain )
194 	{
195 		String username = StringUtils.hasContent( defUsername ) ? defUsername : requestUsername;
196 		String password = StringUtils.hasContent( defPassword ) ? defPassword : requestPassword;
197 		
198 		if( StringUtils.hasContent( username ) || StringUtils.hasContent( password ))
199 		{
200 			// only set if not set in request
201 			String wssType = def.getWssType();
202 			String wssTimeToLive = def.getWssTimeToLive();
203 			
204 			if( wssType == null )
205 			{
206 				String domain = StringUtils.hasContent( defDomain ) ? defDomain : requestDomain;
207 				HttpAuthenticationRequestFilter.initRequestCredentials( context, username, project.getSettings(), password,
208 							domain );
209 			}
210 
211 			if( StringUtils.hasContent( wssType ) || StringUtils.hasContent( wssTimeToLive ) )
212 			{
213 				try
214 				{
215 					// set to null so existing don't get removed
216 					if( wssTimeToLive != null && wssTimeToLive.length() == 0 )
217 						wssTimeToLive = null;
218 					
219 					WssAuthenticationRequestFilter
220 								.setWssHeaders( context, username, password, wssType, wssTimeToLive );
221 				}
222 				catch( Exception e )
223 				{
224 					SoapUI.logError( e );
225 				}
226 			}
227 		}
228 	}
229 
230 	private void copyToRequest( SubmitContext context, WsdlRequest wsdlRequest, EndpointDefaults def,
231 				String requestUsername, String requestPassword, String requestDomain, String defUsername,
232 				String defPassword, String defDomain )
233 	{
234 		// only set if not set in request
235 		String wssType = def.getWssType();
236 	
237 		if( wssType != null )
238 		{
239 			HttpAuthenticationRequestFilter.initRequestCredentials( context, null, project.getSettings(), null, null );
240 		}
241 		else
242 		{
243 			HttpAuthenticationRequestFilter.initRequestCredentials( context, defUsername, project.getSettings(), defPassword,
244 						defDomain );
245 		}
246 		
247 		String wssTimeToLive = def.getWssTimeToLive();
248 		if( wssTimeToLive == null )
249 			wssTimeToLive = "";
250 
251 		try
252 		{
253 			WssAuthenticationRequestFilter.setWssHeaders( context, defUsername, defPassword, wssType, wssTimeToLive );
254 		}
255 		catch( Exception e )
256 		{
257 			SoapUI.logError( e );
258 		}
259 	}
260 
261 	private void complementRequest( SubmitContext context, WsdlRequest wsdlRequest, EndpointDefaults def,
262 				String requestUsername, String requestPassword, String requestDomain, String defUsername,
263 				String defPassword, String defDomain )
264 	{
265 		String username = StringUtils.hasContent( requestUsername ) ? requestUsername : defUsername;
266 		String password = StringUtils.hasContent( requestPassword ) ? requestPassword : defPassword;
267 		
268 		// only set if not set in request
269 		String wssType = StringUtils.isNullOrEmpty( wsdlRequest.getWssPasswordType() ) ? def.getWssType() : ( StringUtils
270 					.hasContent( username ) && StringUtils.hasContent( password ) ) ? null : wsdlRequest
271 					.getWssPasswordType();
272 
273 		String wssTimeToLive = StringUtils.isNullOrEmpty( wsdlRequest.getWssTimeToLive() ) ? def.getWssTimeToLive()
274 					: null;
275 
276 		if( !StringUtils.hasContent( wssType ) && (StringUtils.hasContent( username ) || StringUtils.hasContent( password ) ))
277 		{
278 			String domain = StringUtils.hasContent( requestDomain ) ? requestDomain : defDomain;
279 			HttpAuthenticationRequestFilter.initRequestCredentials( context, username, project.getSettings(), password,
280 						domain );
281 		}
282 		else if( StringUtils.hasContent( wssType ) || StringUtils.hasContent( wssTimeToLive ) )
283 		{
284 			try
285 			{
286 				// set to null so existing don't get removed
287 				if( wssTimeToLive != null && wssTimeToLive.length() == 0 )
288 					wssTimeToLive = null;
289 					
290 				if( StringUtils.hasContent( username ) || StringUtils.hasContent( password ) )
291 					WssAuthenticationRequestFilter
292 								.setWssHeaders( context, username, password, wssType, wssTimeToLive );
293 			}
294 			catch( Exception e )
295 			{
296 				SoapUI.logError( e );
297 			}
298 		}
299 	}
300 
301 	public void release()
302 	{
303 		project.removeProjectListener( projectListener );
304 		for( Interface iface : project.getInterfaceList() )
305 			iface.removePropertyChangeListener( AbstractInterface.ENDPOINT_PROPERTY, propertyChangeListener );
306 	}
307 
308 	private class InternalProjectListener extends ProjectListenerAdapter
309 	{
310 		@Override
311 		public void interfaceAdded( Interface iface )
312 		{
313 			for( String endpoint : iface.getEndpoints() )
314 			{
315 				// ensure we have defaults
316 				getEndpointDefaults( endpoint );
317 			}
318 
319 			iface.addPropertyChangeListener( AbstractInterface.ENDPOINT_PROPERTY, propertyChangeListener );
320 		}
321 
322 		@Override
323 		public void interfaceRemoved( Interface iface )
324 		{
325 			iface.removePropertyChangeListener( AbstractInterface.ENDPOINT_PROPERTY, propertyChangeListener );
326 			removeUnusedEndpoints();
327 		}
328 	}
329 
330 	private class InternalPropertyChangeListener implements PropertyChangeListener
331 	{
332 		public void propertyChange( PropertyChangeEvent evt )
333 		{
334 			// new endpoint?
335 			String newValue = evt.getNewValue() == null ? null : evt.getNewValue().toString();
336 			if( evt.getOldValue() == null )
337 			{
338 				getEndpointDefaults( newValue );
339 			}
340 			// changed endpoint?
341 			else if( newValue != null )
342 			{
343 				String oldValue = evt.getOldValue().toString();
344 				EndpointDefaults def = defaults.containsKey( newValue ) ?
345 						defaults.get( newValue ) : getEndpointDefaults( oldValue );
346 				def.endpointConfig.setStringValue( newValue );
347 				defaults.remove( oldValue );
348 				defaults.put( newValue, def );
349 			}
350 			else
351 			{
352 				removeUnusedEndpoints();
353 			}
354 		}
355 	}
356 
357 	public class EndpointDefaults implements PropertyExpansionContainer
358 	{
359 		private final EndpointConfig endpointConfig;
360 
361 		public EndpointDefaults( EndpointConfig endpointConfig )
362 		{
363 			this.endpointConfig = endpointConfig;
364 
365 			if( !endpointConfig.isSetMode() )
366 				endpointConfig.setMode( EndpointConfig.Mode.COMPLEMENT );
367 		}
368 
369 		public String getDomain()
370 		{
371 			return endpointConfig.getDomain();
372 		}
373 
374 		public String getPassword()
375 		{
376 			return endpointConfig.getPassword();
377 		}
378 
379 		public String getUsername()
380 		{
381 			return endpointConfig.getUsername();
382 		}
383 
384 		public String getWssTimeToLive()
385 		{
386 			return endpointConfig.getWssTimeToLive();
387 		}
388 
389 		public String getWssType()
390 		{
391 			String wssPasswordType = endpointConfig.getWssType();
392 			return StringUtils.isNullOrEmpty( wssPasswordType ) || WsdlRequest.PW_TYPE_NONE.equals( wssPasswordType ) ? null : wssPasswordType;
393 		}
394 
395 		public void setDomain( String arg0 )
396 		{
397 			endpointConfig.setDomain( arg0 );
398 		}
399 
400 		public void setPassword( String arg0 )
401 		{
402 			endpointConfig.setPassword( arg0 );
403 		}
404 
405 		public void setUsername( String arg0 )
406 		{
407 			endpointConfig.setUsername( arg0 );
408 		}
409 
410 		public void setWssTimeToLive( String arg0 )
411 		{
412 			endpointConfig.setWssTimeToLive( arg0 );
413 		}
414 
415 		public String getIncomingWss()
416 		{
417 			return endpointConfig.getIncomingWss();
418 		}
419 
420 		public String getOutgoingWss()
421 		{
422 			return endpointConfig.getOutgoingWss();
423 		}
424 
425 		public void setIncomingWss( String arg0 )
426 		{
427 			endpointConfig.setIncomingWss( arg0 );
428 		}
429 
430 		public void setOutgoingWss( String arg0 )
431 		{
432 			endpointConfig.setOutgoingWss( arg0 );
433 		}
434 
435 		public void setWssType( String wssPasswordType )
436 		{
437 			if( wssPasswordType == null || wssPasswordType.equals( WsdlRequest.PW_TYPE_NONE ))
438 			{
439 				if( endpointConfig.isSetWssType() )
440 					endpointConfig.unsetWssType();
441 			}
442 			else
443 			{
444 				endpointConfig.setWssType( wssPasswordType );
445 			}
446 		}
447 
448 		public EndpointConfig.Mode.Enum getMode()
449 		{
450 			return endpointConfig.getMode();
451 		}
452 
453 		public void setMode( EndpointConfig.Mode.Enum mode )
454 		{
455 			endpointConfig.setMode( mode );
456 		}
457 
458 		protected EndpointConfig getConfig()
459 		{
460 			return endpointConfig;
461 		}
462 
463 		public PropertyExpansion[] getPropertyExpansions()
464 		{
465 			PropertyExpansionsResult result = new PropertyExpansionsResult( project, this );
466 			
467 			result.extractAndAddAll( "username" );
468 			result.extractAndAddAll( "password" );
469 			result.extractAndAddAll( "domain" );
470 			
471 			return result.toArray();
472 		}
473 	}
474 
475 	public EndpointDefaults getEndpointDefaults( String endpoint )
476 	{
477 		if( config == null )
478 			initConfig();
479 
480 		if( !defaults.containsKey( endpoint ) )
481 		{
482 			EndpointConfig newEndpoint = config.addNewEndpoint();
483 			newEndpoint.setStringValue( endpoint );
484 			defaults.put( endpoint, new EndpointDefaults( newEndpoint ) );
485 		}
486 
487 		return defaults.get( endpoint );
488 	}
489 
490 	public void onSave()
491 	{
492 		if( config == null )
493 			return;
494 
495 		removeUnusedEndpoints();
496 
497 		// remove unused
498 		for( int c = 0; c < config.sizeOfEndpointArray(); c++ )
499 		{
500 			EndpointConfig ec = config.getEndpointArray( c );
501 			if( StringUtils.isNullOrEmpty( ec.getDomain() ) && StringUtils.isNullOrEmpty( ec.getUsername() )
502 						&& StringUtils.isNullOrEmpty( ec.getPassword() ) && StringUtils.isNullOrEmpty( ec.getWssType() )
503 						&& StringUtils.isNullOrEmpty( ec.getWssTimeToLive() ) )
504 			{
505 				defaults.remove( ec.getStringValue() );
506 				config.removeEndpoint( c );
507 				c--;
508 			}
509 		}
510 
511 		if( config.sizeOfEndpointArray() == 0 )
512 		{
513 			project.getConfig().unsetEndpointStrategy();
514 			config = null;
515 		}
516 	}
517 
518 	public void importEndpoints( Interface iface )
519 	{
520 		EndpointStrategy ep = iface.getProject().getEndpointStrategy();
521 		if( ep instanceof DefaultEndpointStrategy )
522 		{
523 			DefaultEndpointStrategy dep = ( DefaultEndpointStrategy ) ep;
524 			String[] endpoints = iface.getEndpoints();
525 
526 			for( String endpoint : endpoints )
527 			{
528 				getEndpointDefaults( endpoint ).getConfig().set( dep.getEndpointDefaults( endpoint ).getConfig() );
529 			}
530 		}
531 	}
532 
533 	public JComponent getConfigurationPanel( Interface iface )
534 	{
535 		return new DefaultEndpointStrategyConfigurationPanel( iface, this );
536 	}
537 
538 	public void afterRequest( SubmitContext context, Response response )
539 	{
540 	}
541 
542 	public PropertyExpansion[] getPropertyExpansions()
543 	{
544 		PropertyExpansionsResult result = new PropertyExpansionsResult( project, this );
545 		
546 		for( EndpointDefaults ed : defaults.values()  )
547 		{
548 			result.addAll( ed.getPropertyExpansions() );
549 		}
550 		
551 		return result.toArray();
552 	}
553 
554 	public void changeEndpoint(String oldEndpoint, String newEndpoint)
555 	{
556 		EndpointDefaults endpointDefaults = defaults.remove( oldEndpoint );
557 		if( endpointDefaults != null )
558 		{
559 			endpointDefaults.getConfig().setStringValue(newEndpoint);
560 			defaults.put(newEndpoint, endpointDefaults);
561 		}
562 	}
563 
564 	public void afterRequest(SubmitContext context, Request request)
565 	{
566 	}
567 }