View Javadoc

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