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