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.support;
14  
15  import java.io.File;
16  import java.io.FileInputStream;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  import java.util.Set;
28  
29  import javax.xml.namespace.QName;
30  
31  import org.apache.xmlbeans.XmlString;
32  
33  import com.eviware.soapui.SoapUI;
34  import com.eviware.soapui.config.PropertiesTypeConfig;
35  import com.eviware.soapui.config.PropertyConfig;
36  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
37  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
38  import com.eviware.soapui.model.ModelItem;
39  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
40  import com.eviware.soapui.model.support.TestPropertyUtils;
41  import com.eviware.soapui.model.testsuite.RenameableTestProperty;
42  import com.eviware.soapui.model.testsuite.TestProperty;
43  import com.eviware.soapui.model.testsuite.TestPropertyListener;
44  import com.eviware.soapui.support.StringUtils;
45  
46  public class XmlBeansPropertiesTestPropertyHolder implements MutableTestPropertyHolder, Map<String, TestProperty>
47  {
48  	private PropertiesTypeConfig config;
49  	private List<PropertiesStepProperty> properties = new ArrayList<PropertiesStepProperty>();
50  	private Map<String, PropertiesStepProperty> propertyMap = new HashMap<String, PropertiesStepProperty>();
51  	private Set<TestPropertyListener> listeners = new HashSet<TestPropertyListener>();
52  	private ModelItem modelItem;
53  	private Properties overrideProperties;
54  	private String propertiesLabel = "Test Properties";
55  
56  	public XmlBeansPropertiesTestPropertyHolder( ModelItem modelItem, PropertiesTypeConfig config )
57  	{
58  		this.modelItem = modelItem;
59  		this.config = config;
60  
61  		for( int c = 0; c < config.sizeOfPropertyArray(); c++ )
62  		{
63  			PropertyConfig propertyConfig = config.getPropertyArray( c );
64  			if( StringUtils.hasContent( propertyConfig.getName() ) )
65  			{
66  				addProperty( propertyConfig, false, null );
67  			}
68  			else
69  			{
70  				config.removeProperty( c );
71  				c-- ;
72  			}
73  		}
74  	}
75  
76  	protected PropertiesStepProperty addProperty( PropertyConfig propertyConfig, boolean notify,
77  			TestProperty virtualProperty )
78  	{
79  		PropertiesStepProperty propertiesStepProperty = new PropertiesStepProperty( propertyConfig, virtualProperty );
80  
81  		properties.add( propertiesStepProperty );
82  
83  		sortVirtualLast();
84  
85  		propertyMap.put( propertiesStepProperty.getName().toUpperCase(), propertiesStepProperty );
86  
87  		if( notify )
88  		{
89  			firePropertyAdded( propertiesStepProperty.getName() );
90  		}
91  
92  		return propertiesStepProperty;
93  	}
94  
95  	/***
96  	 * sort properties list and make sure that virtualproperties are always
97  	 * placed after properties
98  	 */
99  	private void sortVirtualLast()
100 	{
101 		List<PropertiesStepProperty> virtualProperties = new ArrayList<PropertiesStepProperty>();
102 		List<PropertiesStepProperty> nonVirtualProperties = new ArrayList<PropertiesStepProperty>();
103 
104 		for( PropertiesStepProperty psp : properties )
105 		{
106 			if( psp.isVirtualProperty() )
107 			{
108 				if( !virtualProperties.contains( psp ) )
109 					virtualProperties.add( psp );
110 			}
111 			else
112 			{
113 				nonVirtualProperties.add( psp );
114 			}
115 		}
116 		properties.clear();
117 		properties.addAll( nonVirtualProperties );
118 		properties.addAll( virtualProperties );
119 	}
120 
121 	private void firePropertyAdded( String name )
122 	{
123 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
124 		for( TestPropertyListener listener : listenersArray )
125 		{
126 			listener.propertyAdded( name );
127 		}
128 	}
129 
130 	private void firePropertyRemoved( String name )
131 	{
132 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
133 		for( TestPropertyListener listener : listenersArray )
134 		{
135 			listener.propertyRemoved( name );
136 		}
137 	}
138 
139 	private void firePropertyMoved( String name, int oldIndex, int newIndex )
140 	{
141 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
142 		for( TestPropertyListener listener : listenersArray )
143 		{
144 			listener.propertyMoved( name, oldIndex, newIndex );
145 		}
146 	}
147 
148 	private void firePropertyRenamed( String oldName, String newName )
149 	{
150 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
151 		for( TestPropertyListener listener : listenersArray )
152 		{
153 			listener.propertyRenamed( oldName, newName );
154 		}
155 	}
156 
157 	private void firePropertyValueChanged( String name, String oldValue, String newValue )
158 	{
159 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
160 		for( TestPropertyListener listener : listenersArray )
161 		{
162 			listener.propertyValueChanged( name, oldValue, newValue );
163 		}
164 	}
165 
166 	public TestProperty addProperty( String name )
167 	{
168 		PropertyConfig propertyConfig = config.addNewProperty();
169 		propertyConfig.setName( name );
170 		return addProperty( propertyConfig, true, null );
171 	}
172 
173 	public TestProperty addVirtualProperty( String key, TestProperty virtualProperty )
174 	{
175 		PropertyConfig propertyConfig = PropertyConfig.Factory.newInstance();
176 		propertyConfig.setName( key );
177 		return addProperty( propertyConfig, true, virtualProperty );
178 	}
179 
180 	public void addTestPropertyListener( TestPropertyListener listener )
181 	{
182 		listeners.add( listener );
183 	}
184 
185 	public PropertiesStepProperty getProperty( String name )
186 	{
187 		return propertyMap.get( name.toUpperCase() );
188 	}
189 
190 	public String[] getPropertyNames()
191 	{
192 		String[] result = new String[properties.size()];
193 		for( int c = 0; c < properties.size(); c++ )
194 			result[c] = properties.get( c ).getName();
195 
196 		return result;
197 	}
198 
199 	public List<TestProperty> getPropertyList()
200 	{
201 		List<TestProperty> result = new ArrayList<TestProperty>();
202 
203 		for( TestProperty property : properties )
204 			result.add( property );
205 
206 		return result;
207 	}
208 
209 	public String getPropertyValue( String name )
210 	{
211 		TestProperty property = getProperty( name );
212 		return property == null ? null : property.getValue();
213 	}
214 
215 	public TestProperty removeProperty( String propertyName )
216 	{
217 		TestProperty property = getProperty( propertyName );
218 		if( property != null )
219 		{
220 			if( property instanceof PropertiesStepProperty && ( ( PropertiesStepProperty )property ).isVirtualProperty() )
221 			{
222 				return property;
223 			}
224 			int ix = properties.indexOf( property );
225 			propertyMap.remove( propertyName.toUpperCase() );
226 			properties.remove( ix );
227 			firePropertyRemoved( propertyName );
228 			config.removeProperty( ix );
229 			return property;
230 		}
231 
232 		return null;
233 	}
234 
235 	public void removeTestPropertyListener( TestPropertyListener listener )
236 	{
237 		listeners.remove( listener );
238 	}
239 
240 	public void setPropertyValue( String name, String value )
241 	{
242 		PropertiesStepProperty property = getProperty( name );
243 		if( property != null )
244 			property.setValue( value );
245 		else
246 			addProperty( name ).setValue( value );
247 	}
248 
249 	public void resetPropertiesConfig( PropertiesTypeConfig config )
250 	{
251 		this.config = config;
252 
253 		for( int c = 0; c < config.sizeOfPropertyArray(); c++ )
254 		{
255 			properties.get( c ).setConfig( config.getPropertyArray( c ) );
256 		}
257 	}
258 
259 	public boolean renameProperty( String name, String newName )
260 	{
261 		if( getProperty( newName ) != null )
262 			return false;
263 
264 		PropertiesStepProperty property = getProperty( name );
265 		if( property == null )
266 			return false;
267 
268 		property.setName( newName );
269 		return true;
270 	}
271 
272 	/***
273 	 * Internal property class
274 	 * 
275 	 * @author ole
276 	 */
277 
278 	public class PropertiesStepProperty implements RenameableTestProperty
279 	{
280 		private PropertyConfig propertyConfig;
281 		private final TestProperty virtualProperty;
282 
283 		public PropertiesStepProperty( PropertyConfig propertyConfig, TestProperty virtualProperty )
284 		{
285 			this.propertyConfig = propertyConfig;
286 			this.virtualProperty = virtualProperty;
287 		}
288 
289 		public boolean isVirtualProperty()
290 		{
291 			return virtualProperty != null;
292 		}
293 
294 		public void setConfig( PropertyConfig propertyConfig )
295 		{
296 			this.propertyConfig = propertyConfig;
297 		}
298 
299 		public String getName()
300 		{
301 			return propertyConfig.getName();
302 		}
303 
304 		public void setName( String name )
305 		{
306 			String oldName = getName();
307 			propertyConfig.setName( name );
308 
309 			propertyMap.remove( oldName.toUpperCase() );
310 			propertyMap.put( name.toUpperCase(), this );
311 
312 			firePropertyRenamed( oldName, name );
313 		}
314 
315 		public String getDescription()
316 		{
317 			return null;
318 		}
319 
320 		public String getValue()
321 		{
322 			if( overrideProperties != null && overrideProperties.containsKey( getName() ) )
323 				return overrideProperties.getProperty( getName() );
324 
325 			if( virtualProperty != null )
326 				return virtualProperty.getValue();
327 
328 			return propertyConfig.getValue();
329 		}
330 
331 		public void setValue( String value )
332 		{
333 			String oldValue = getValue();
334 			propertyConfig.setValue( value );
335 
336 			if( overrideProperties != null && overrideProperties.containsKey( getName() ) )
337 			{
338 				overrideProperties.remove( getName() );
339 				if( overrideProperties.isEmpty() )
340 					overrideProperties = null;
341 			}
342 
343 			firePropertyValueChanged( getName(), oldValue, value );
344 		}
345 
346 		public boolean isReadOnly()
347 		{
348 			return false;
349 		}
350 
351 		public QName getType()
352 		{
353 			return XmlString.type.getName();
354 		}
355 
356 		public ModelItem getModelItem()
357 		{
358 			return modelItem;
359 		}
360 
361 		public String getDefaultValue()
362 		{
363 			return null;
364 		}
365 	}
366 
367 	public int saveTo( String fileName ) throws IOException
368 	{
369 		return TestPropertyUtils.saveTo( this, fileName );
370 	}
371 
372 	public int getPropertyCount()
373 	{
374 		return properties.size();
375 	}
376 
377 	public TestProperty getPropertyAt( int index )
378 	{
379 		return properties.get( index );
380 	}
381 
382 	public Map<String, TestProperty> getProperties()
383 	{
384 		Map<String, TestProperty> result = new HashMap<String, TestProperty>();
385 		for( TestProperty property : propertyMap.values() )
386 		{
387 			result.put( property.getName(), property );
388 		}
389 
390 		return result;
391 	}
392 
393 	public boolean hasProperty( String name )
394 	{
395 		return propertyMap.containsKey( name.toUpperCase() );
396 	}
397 
398 	public int addPropertiesFromFile( String propFile )
399 	{
400 		if( !StringUtils.hasContent( propFile ) )
401 			return 0;
402 
403 		try
404 		{
405 			InputStream input = null;
406 
407 			File file = new File( propFile );
408 			if( file.exists() )
409 			{
410 				input = new FileInputStream( file );
411 			}
412 			else if( propFile.toLowerCase().startsWith( "http://" ) || propFile.toLowerCase().startsWith( "https://" ) )
413 			{
414 				UrlWsdlLoader loader = new UrlWsdlLoader( propFile, getModelItem() );
415 				loader.setUseWorker( false );
416 				input = loader.load();
417 			}
418 
419 			if( input != null )
420 			{
421 				if( overrideProperties == null )
422 					overrideProperties = new Properties();
423 
424 				int sz = overrideProperties.size();
425 				overrideProperties.load( input );
426 
427 				for( Object key : overrideProperties.keySet() )
428 				{
429 					String name = key.toString();
430 					if( !hasProperty( name ) )
431 						addProperty( name );
432 				}
433 
434 				return overrideProperties.size() - sz;
435 			}
436 		}
437 		catch( Exception e )
438 		{
439 			SoapUI.logError( e );
440 		}
441 
442 		return 0;
443 	}
444 
445 	public ModelItem getModelItem()
446 	{
447 		return modelItem;
448 	}
449 
450 	public PropertyExpansion[] getPropertyExpansions()
451 	{
452 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
453 
454 		return result.toArray( new PropertyExpansion[result.size()] );
455 	}
456 
457 	public void moveProperty( String propertyName, int targetIndex )
458 	{
459 		PropertiesStepProperty property = getProperty( propertyName );
460 		int ix = properties.indexOf( property );
461 
462 		if( ix == targetIndex )
463 			return;
464 
465 		if( targetIndex < 0 )
466 			targetIndex = 0;
467 
468 		String value = property.getValue();
469 		config.removeProperty( ix );
470 
471 		PropertyConfig propertyConfig = null;
472 
473 		if( targetIndex < properties.size() )
474 		{
475 			properties.add( targetIndex, properties.remove( ix ) );
476 			propertyConfig = config.insertNewProperty( targetIndex );
477 		}
478 		else
479 		{
480 			properties.add( properties.remove( ix ) );
481 			propertyConfig = config.addNewProperty();
482 		}
483 
484 		propertyConfig.setName( propertyName );
485 		propertyConfig.setValue( value );
486 
487 		resetPropertiesConfig( config );
488 
489 		if( targetIndex > properties.size() )
490 			targetIndex = properties.size();
491 
492 		firePropertyMoved( propertyName, ix, targetIndex );
493 	}
494 
495 	public void clear()
496 	{
497 		while( size() > 0 )
498 			removeProperty( getPropertyAt( 0 ).getName() );
499 	}
500 
501 	public boolean containsKey( Object key )
502 	{
503 		return hasProperty( ( String )key );
504 	}
505 
506 	public boolean containsValue( Object value )
507 	{
508 		return propertyMap.containsValue( value );
509 	}
510 
511 	public Set<java.util.Map.Entry<String, TestProperty>> entrySet()
512 	{
513 		HashSet<java.util.Map.Entry<String, TestProperty>> result = new HashSet<Entry<String, TestProperty>>();
514 
515 		for( TestProperty p : propertyMap.values() )
516 		{
517 			// This does not compile on JDK 1.5:
518 			// result.add( new java.util.HashMap.SimpleEntry<String,
519 			// TestProperty>(p.getName(), p));
520 			result.add( new HashMapEntry<String, TestProperty>( p.getName(), p ) );
521 		}
522 
523 		return result;
524 	}
525 
526 	private static class HashMapEntry<K, V> implements java.util.Map.Entry<K, V>
527 	{
528 		private K key;
529 		private V value;
530 
531 		public HashMapEntry( K key, V value )
532 		{
533 			this.key = key;
534 			this.value = value;
535 		}
536 
537 		public K getKey()
538 		{
539 			return key;
540 		}
541 
542 		public V getValue()
543 		{
544 			return value;
545 		}
546 
547 		public V setValue( V value )
548 		{
549 			throw new UnsupportedOperationException();
550 		}
551 	}
552 
553 	public TestProperty get( Object key )
554 	{
555 		return getProperty( ( String )key );
556 	}
557 
558 	public boolean isEmpty()
559 	{
560 		return propertyMap.isEmpty();
561 	}
562 
563 	public Set<String> keySet()
564 	{
565 		return new HashSet<String>( Arrays.asList( getPropertyNames() ) );
566 	}
567 
568 	public TestProperty put( String key, TestProperty value )
569 	{
570 		TestProperty result = addProperty( key );
571 		result.setValue( value.getValue() );
572 		return result;
573 	}
574 
575 	public void putAll( Map<? extends String, ? extends TestProperty> m )
576 	{
577 		for( TestProperty p : m.values() )
578 		{
579 			addProperty( p.getName() ).setValue( p.getValue() );
580 		}
581 	}
582 
583 	public TestProperty remove( Object key )
584 	{
585 		return removeProperty( ( String )key );
586 	}
587 
588 	public int size()
589 	{
590 		return propertyMap.size();
591 	}
592 
593 	public Collection<TestProperty> values()
594 	{
595 		ArrayList<TestProperty> result = new ArrayList<TestProperty>();
596 		result.addAll( propertyMap.values() );
597 		return result;
598 	}
599 
600 	public String getPropertiesLabel()
601 	{
602 		return propertiesLabel;
603 	}
604 
605 	public void setPropertiesLabel( String propertiesLabel )
606 	{
607 		this.propertiesLabel = propertiesLabel;
608 	}
609 }