View Javadoc

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